#include <bits/stdc++.h>
using namespace std;
template <typename A>
string to_string(A* ptr) {
  stringstream ss;
  ss << "0x" << std::setw(16) << std::setfill('0') << std::hex
     << (uint64_t)(uintptr_t)ptr;
  return ss.str();
}
string to_string(char c) { return ((string) "'" + c) + "'"; }
template <typename A, typename B>
string to_string(pair<A, B> p);
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p);
template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p);
string to_string(const string& s) { return '"' + s + '"'; }
string to_string(const char* s) { return to_string((string)s); }
string to_string(bool b) { return (b ? "true" : "false"); }
string to_string(vector<bool> v) {
  bool first = true;
  string res = "{";
  for (int i = 0; i < static_cast<int>(v.size()); i++) {
    if (!first) {
      res += ", ";
    }
    first = false;
    res += to_string(v[i]);
  }
  res += "}";
  return res;
}
template <size_t N>
string to_string(bitset<N> v) {
  string res = "";
  for (size_t i = 0; i < N; i++) {
    res += static_cast<char>('0' + v[i]);
  }
  return res;
}
template <typename A>
string to_string(A v) {
  bool first = true;
  string res = "{";
  for (const auto& x : v) {
    if (!first) {
      res += ", ";
    }
    first = false;
    res += to_string(x);
  }
  res += "}";
  return res;
}
template <typename A, typename B>
string to_string(pair<A, B> p) {
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {
  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " +
         to_string(get<2>(p)) + ")";
}
template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p) {
  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " +
         to_string(get<2>(p)) + ", " + to_string(get<3>(p)) + ")";
}
void debug_out() { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
  cerr << " " << to_string(H);
  debug_out(T...);
}
struct node {
  bool lazy;
  int len;
  int cnt_L, cnt_R;
  int pref_L, pref_RL;
  int suff_R, suff_RL;
  int pref_R, pref_LR;
  int suff_L, suff_LR;
  int max_LR, max_RL;
  void toggle2() {
    lazy = !lazy;
    swap(cnt_L, cnt_R);
    swap(pref_L, pref_R);
    swap(pref_RL, pref_LR);
    swap(suff_R, suff_L);
    swap(suff_RL, suff_LR);
    swap(max_LR, max_RL);
  }
  node()
      : lazy(false),
        len(0),
        cnt_L(0),
        cnt_R(0),
        pref_L(0),
        pref_RL(0),
        suff_R(0),
        suff_RL(0),
        pref_R(0),
        pref_LR(0),
        suff_L(0),
        suff_LR(0),
        max_LR(0),
        max_RL(0) {}
  node(char c)
      : lazy(false),
        len(1),
        cnt_L((c == '<' ? 1 : 0)),
        cnt_R((c == '>' ? 1 : 0)),
        pref_L((c == '<' ? 1 : 0)),
        pref_RL(1),
        suff_R((c == '>' ? 1 : 0)),
        suff_RL(1),
        pref_R((c == '>' ? 1 : 0)),
        pref_LR(1),
        suff_L((c == '<' ? 1 : 0)),
        suff_LR(1),
        max_LR(1),
        max_RL(1) {
    assert(c == '<' || c == '>');
  }
  node(const node A, const node B)
      : lazy(false),
        len(A.len + B.len),
        cnt_L(A.cnt_L + B.cnt_L),
        cnt_R(A.cnt_R + B.cnt_R),
        pref_L(A.pref_L),
        pref_RL(A.pref_RL),
        suff_R(B.suff_R),
        suff_RL(B.suff_RL),
        pref_R(A.pref_R),
        pref_LR(A.pref_LR),
        suff_L(B.suff_L),
        suff_LR(B.suff_LR),
        max_LR(max(A.max_LR, B.max_LR)),
        max_RL(max(A.max_RL, B.max_RL)) {
    if (A.cnt_L == A.len) pref_L = A.len + B.pref_L;
    if (B.cnt_R == B.len) suff_R = A.suff_R + B.len;
    if (A.cnt_R == A.len) pref_R = A.len + B.pref_R;
    if (B.cnt_L == B.len) suff_L = A.suff_L + B.len;
    if (A.pref_RL == A.len) {
      pref_RL = A.len + B.pref_L;
    }
    if (A.pref_R == A.len) {
      pref_RL = max(pref_RL, A.len + B.pref_RL);
    }
    if (B.suff_RL == B.len) {
      suff_RL = A.suff_R + B.len;
    }
    if (B.suff_L == B.len) {
      suff_RL = max(suff_RL, A.suff_RL + B.len);
    }
    if (A.pref_LR == A.len) {
      pref_LR = A.len + B.pref_R;
    }
    if (A.pref_L == A.len) {
      pref_LR = max(pref_LR, A.len + B.pref_LR);
    }
    if (B.suff_LR == B.len) {
      suff_LR = A.suff_L + B.len;
    }
    if (B.suff_R == B.len) {
      suff_LR = max(suff_LR, A.suff_LR + B.len);
    }
    max_RL = max(max_RL, A.suff_R + B.pref_RL);
    max_RL = max(max_RL, A.suff_RL + B.pref_L);
    max_LR = max(max_LR, A.suff_L + B.pref_LR);
    max_LR = max(max_LR, A.suff_LR + B.pref_R);
  }
};
string to_string(const node& A) {
  stringstream ss;
  ss << "lazy: " << A.lazy << endl;
  ss << "len: " << A.len << endl;
  ss << "cnt_L: " << A.cnt_L << endl;
  ss << "cnt_R: " << A.cnt_R << endl;
  ss << "pref_L: " << A.pref_L << endl;
  ss << "pref_RL: " << A.pref_RL << endl;
  ss << "suff_R: " << A.suff_R << endl;
  ss << "suff_RL: " << A.suff_RL << endl;
  ss << "pref_R: " << A.pref_R << endl;
  ss << "pref_LR: " << A.pref_LR << endl;
  ss << "suff_L: " << A.suff_L << endl;
  ss << "suff_LR: " << A.suff_LR << endl;
  ss << "max_LR: " << A.max_LR << endl;
  ss << "max_RL: " << A.max_RL << endl;
  return ss.str();
}
node Identity() {
  node R;
  return R;
}
node unite(node A, node B) {
  node R(A, B);
  return R;
}
struct seg_tree {
  int N, pow2;
  vector<node> V;
  seg_tree(string s) : N(1), pow2(1), V() {
    N = (int)s.size();
    pow2 = 1;
    while (pow2 < N) pow2 *= 2;
    V = vector<node>(2 * pow2);
    for (int i = 0; i < N; i++) V[i + pow2] = node(s[i]);
    for (int i = N; i < pow2; i++) V[i + pow2] = Identity();
    for (int i = pow2 - 1; i >= 1; i--) V[i] = unite(V[2 * i], V[2 * i + 1]);
  }
  void update(int L, int R, int qq) {
    42;
    assert(0 <= L && L <= R && R < N);
    upd_internal(L, R, 0, pow2 - 1, 1);
  }
  void upd_internal(int L, int R, int LB, int RB, int idx) {
    if (L > R) return;
    assert(LB <= L && L <= R && R <= RB);
    if (LB == L && R == RB) {
      42;
      V[idx].toggle2();
      return;
    }
    int MB = (LB + RB) / 2;
    if (V[idx].lazy) {
      upd_internal(LB, MB, LB, MB, 2 * idx);
      upd_internal(MB + 1, RB, MB + 1, RB, 2 * idx + 1);
    }
    upd_internal(L, min(R, MB), LB, MB, 2 * idx);
    upd_internal(max(MB + 1, L), R, MB + 1, RB, 2 * idx + 1);
    V[idx] = unite(V[2 * idx], V[2 * idx + 1]);
  }
  int query(int L, int R) {
    assert(0 <= L && L <= R && R < N);
    node tmp = query_internal(L, R, 0, pow2 - 1, 1);
    return tmp.max_RL;
  }
  char query_at_point(int i) {
    node res = query_internal(i, i, 0, pow2 - 1, 1);
    char c = (res.cnt_L == 1 ? '<' : '>');
    return c;
  }
  node query_internal(int L, int R, int LB, int RB, int idx) {
    if (L > R) return Identity();
    assert(LB <= L && L <= R && R <= RB);
    if (LB == L && R == RB) {
      return V[idx];
    }
    int MB = (LB + RB) / 2;
    if (V[idx].lazy) {
      upd_internal(LB, MB, LB, MB, 2 * idx);
      upd_internal(MB + 1, RB, MB + 1, RB, 2 * idx + 1);
      V[idx] = unite(V[2 * idx], V[2 * idx + 1]);
      V[idx].lazy = false;
    }
    node left = query_internal(L, min(R, MB), LB, MB, 2 * idx);
    node right = query_internal(max(MB + 1, L), R, MB + 1, RB, 2 * idx + 1);
    return unite(left, right);
  }
};
const int MAXN = 5e5 + 99;
const int MAXQ = 1e5 + 99;
int n, q;
string s;
int main() {
  int TT;
  TT = 1;
  for (int ttt = 0; ttt < TT; ttt++) {
    cin >> n >> q;
    cin >> s;
    seg_tree ST(s);
    for (int qq = 0; qq < q; qq++) {
      int l, r;
      cin >> l >> r;
      l--;
      r--;
      ST.update(l, r, qq);
      int res = ST.query(l, r);
      cout << res << '\n';
    }
  }
  return 0;
}
