#include<bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>

// using namespace __gnu_pbds;
using namespace std;

#define fbo find_by_order
#define ook order_of_key
#define fi first
#define se second
#define long long long
typedef pair<int,int> ii;
typedef pair<int,ii> iii;
typedef vector<int> vi;
typedef vector<ii> vii;
// typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
// void initiate_random() { mt19937_64 rng(std::chrono::system_clock::now().time_since_epoch().count()); }

struct data
{
	int mx; // maximum
	int kir, kan; // hole left, hole right,
	char l, r; // most left char, most right char;
	bool bol;

	data()
	{
		mx = -1;
	}
	data(char c)
	{
		bol = 1;
		mx = kir = kan = 1;
		l = r = c;
	}
};

int n, q;
bool lazy[2000003];
data tree[2000003][2];
char A[500003];

data merge(data a, data b)
{
	if(a.mx == -1) return b;
	if(b.mx == -1) return a;

    data ans;
    ans.mx = max(a.mx, b.mx);
    if(a.r == '>' || b.l == '<')
    	ans.mx = max(ans.mx, a.kan + b.kir);

    ans.l = a.l;
    ans.r = b.r;
    ans.bol = (a.bol && b.bol && (a.r == '>' || b.l == '<'));

    if(ans.bol) ans.kir = ans.kan = ans.mx;
    else
    {
    	if(b.bol && b.l == '<')
    		ans.kan = (b.kir+a.kan);
	    else if(b.bol && a.r == '>')
	    	ans.kan = (b.kan+a.kan);
	    else ans.kan = b.kan;

	    if(a.bol && a.r == '>')
	    	ans.kir = (a.kan+b.kir);
	    else if(a.bol && b.l == '<')
	    	ans.kir = (a.kir+b.kir);
	    else ans.kir = a.kir;
	}

    return ans;
}

void build(int pos, int kir, int kan)
{
	if(kir == kan)
	{
		if(A[kir] == '<')
		{
			tree[pos][0] = data('<');
			tree[pos][1] = data('>');
		}
		else
		{
			tree[pos][0] = data('>');
			tree[pos][1] = data('<');
		}
		return;
	}

	int mid = (kir+kan)/2;
	build(pos*2, kir, mid);
	build(pos*2+1, mid+1, kan);
	tree[pos][0] = merge(tree[pos*2][0], tree[pos*2+1][0]);
	tree[pos][1] = merge(tree[pos*2][1], tree[pos*2+1][1]);

	// printf("pos  	: %d %d\n", kir, kan);
	// printf("tree[0]	: %d %d %d %c %c %d\n", tree[pos][0].mx, tree[pos][0].kir, tree[pos][0].kan,
	// 									 tree[pos][0].l, tree[pos][0].r, tree[pos][0].bol);
	// printf("tree[1]	: %d %d %d %c %c %d\n", tree[pos][1].mx, tree[pos][1].kir, tree[pos][1].kan,
	// 									 tree[pos][1].l, tree[pos][1].r, tree[pos][1].bol);
}

void ceklazy(int pos, int kir, int kan)
{
	if(lazy[pos])
	{
		swap(tree[pos][0],tree[pos][1]);
		if(kir != kan)
		{
			lazy[pos*2] ^= 1;
			lazy[pos*2+1] ^= 1;
		}
		lazy[pos] = 0;
	}
}

void update(int pos, int kir, int kan, int qkir, int qkan)
{
	// printf("%d %d %d\n", pos, kir, kan); fflush(stdout);
	ceklazy(pos, kir, kan);
	if(qkir <= kir && kan <= qkan)
	{
		lazy[pos] = 1;
		ceklazy(pos, kir, kan);
		return;
	}
	if(qkan < kir || kan < qkir) return;

	int mid = (kir+kan)/2;
	update(pos*2, kir, mid, qkir, qkan);
	update(pos*2+1, mid+1, kan, qkir, qkan);
	tree[pos][0] = merge(tree[pos*2][0], tree[pos*2+1][0]);
	tree[pos][1] = merge(tree[pos*2][1], tree[pos*2+1][1]);
}

data query(int pos, int kir, int kan, int qkir, int qkan)
{
	ceklazy(pos, kir, kan);
	if(qkir <= kir && kan <= qkan) return tree[pos][0];
	if(qkan < kir || kan < qkir) return data();

	int mid = (kir+kan)/2;
	data a = query(pos*2, kir, mid, qkir, qkan);
	data b = query(pos*2+1, mid+1, kan, qkir, qkan);
	return merge(a, b);
}

void preorder(int pos, int kir, int kan)
{
	printf("pos  	: %d %d %d\n", kir, kan, lazy[pos]);
	printf("tree[0]	: %d %d %d %c %c %d\n", tree[pos][0].mx, tree[pos][0].kir, tree[pos][0].kan,
										 tree[pos][0].l, tree[pos][0].r, tree[pos][0].bol);
	printf("tree[1]	: %d %d %d %c %c %d\n", tree[pos][1].mx, tree[pos][1].kir, tree[pos][1].kan,
										 tree[pos][1].l, tree[pos][1].r, tree[pos][1].bol);
	if(kir == kan) return;
	preorder(pos*2, kir, (kir+kan)/2);
	preorder(pos*2+1, (kir+kan)/2+1, kan);
}

int main()
{
	// ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	// freopen("input.in", "r", stdin);
	scanf("%d %d\n", &n, &q);
	for(int i = 1; i <= n; i++)
		scanf("%c", &A[i]);

	build(1, 1, n);
	// preorder(1, 1, n);
	while(q--)
	{
		int a, b;
		scanf("%d %d", &a, &b);
		update(1, 1, n, a, b);
		printf("%d\n", query(1, 1, n, a, b).mx);
		// preorder(1, 1, n);
		// return 0;
	}
}


#include<bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>

// using namespace __gnu_pbds;
using namespace std;

#define fbo find_by_order
#define ook order_of_key
#define fi first
#define se second
#define long long long
typedef pair<int,int> ii;
typedef pair<int,ii> iii;
typedef vector<int> vi;
typedef vector<ii> vii;
// typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
// void initiate_random() { mt19937_64 rng(std::chrono::system_clock::now().time_since_epoch().count()); }

struct data
{
	int mx; // maximum
	int kir, kan; // hole left, hole right,
	char ckir, ckan; // most left char, most right char;
	bool bol;

	data()
	{
		mx = -1;
	}
	data(char c)
	{
		bol = 1;
		mx = kir = kan = 1;
		ckir = ckan = c;
	}
};

int n, q;
bool lazy[2000003];
data tree[2000003][2];
char A[500003];

data merge(data a, data b)
{
	if(a.mx == -1) return b;
	if(b.mx == -1) return a;

    data ans;
    ans.mx = max(a.mx, b.mx);
    if(a.ckan == '>' || b.ckir == '<')
    	ans.mx = max(ans.mx, a.kan + b.kir);

    ans.ckir = a.ckir;
    ans.ckan = b.ckan;
    ans.bol = (a.bol && b.bol && (a.ckan == '>' || b.ckir == '<'));

    if(ans.bol) ans.kir = ans.kan = ans.mx;
    else
    {
	    if(b.bol && a.ckan == '>')
	    	ans.kan = (b.kan+a.kan);
	    else ans.kan = b.kan;

	    if(a.bol && b.ckir == '<')
	    	ans.kir = (a.kir+b.kir);
	    else ans.kir = a.kir;
	}

    return ans;
}

void build(int pos, int kir, int kan)
{
	if(kir == kan)
	{
		if(A[kir] == '<')
		{
			tree[pos][0] = data('<');
			tree[pos][1] = data('>');
		}
		else
		{
			tree[pos][0] = data('>');
			tree[pos][1] = data('<');
		}
		return;
	}

	int mid = (kir+kan)/2;
	build(pos*2, kir, mid);
	build(pos*2+1, mid+1, kan);
	tree[pos][0] = merge(tree[pos*2][0], tree[pos*2+1][0]);
	tree[pos][1] = merge(tree[pos*2][1], tree[pos*2+1][1]);

	// printf("pos  	: %d %d\n", kir, kan);
	// printf("tree[0]	: %d %d %d %c %c %d\n", tree[pos][0].mx, tree[pos][0].kir, tree[pos][0].kan,
	// 									 tree[pos][0].ckir, tree[pos][0].ckan, tree[pos][0].bol);
	// printf("tree[1]	: %d %d %d %c %c %d\n", tree[pos][1].mx, tree[pos][1].kir, tree[pos][1].kan,
	// 									 tree[pos][1].ckir, tree[pos][1].ckan, tree[pos][1].bol);
}

void ceklazy(int pos, int kir, int kan)
{
	if(lazy[pos])
	{
		swap(tree[pos][0],tree[pos][1]);
		if(kir != kan)
		{
			lazy[pos*2] ^= 1;
			lazy[pos*2+1] ^= 1;
		}
		lazy[pos] = 0;
	}
}

void update(int pos, int kir, int kan, int qkir, int qkan)
{
	// printf("%d %d %d\n", pos, kir, kan); fflush(stdout);
	ceklazy(pos, kir, kan);
	if(qkir <= kir && kan <= qkan)
	{
		lazy[pos] = 1;
		ceklazy(pos, kir, kan);
		return;
	}
	if(qkan < kir || kan < qkir) return;

	int mid = (kir+kan)/2;
	update(pos*2, kir, mid, qkir, qkan);
	update(pos*2+1, mid+1, kan, qkir, qkan);
	tree[pos][0] = merge(tree[pos*2][0], tree[pos*2+1][0]);
	tree[pos][1] = merge(tree[pos*2][1], tree[pos*2+1][1]);
}

data query(int pos, int kir, int kan, int qkir, int qkan)
{
	ceklazy(pos, kir, kan);
	if(qkir <= kir && kan <= qkan) return tree[pos][0];
	if(qkan < kir || kan < qkir) return data();

	int mid = (kir+kan)/2;
	data a = query(pos*2, kir, mid, qkir, qkan);
	data b = query(pos*2+1, mid+1, kan, qkir, qkan);
	return merge(a, b);
}

void preorder(int pos, int kir, int kan)
{
	printf("pos  	: %d %d %d\n", kir, kan, lazy[pos]);
	printf("tree[0]	: %d %d %d %c %c %d\n", tree[pos][0].mx, tree[pos][0].kir, tree[pos][0].kan,
										 tree[pos][0].ckir, tree[pos][0].ckan, tree[pos][0].bol);
	printf("tree[1]	: %d %d %d %c %c %d\n", tree[pos][1].mx, tree[pos][1].kir, tree[pos][1].kan,
										 tree[pos][1].ckir, tree[pos][1].ckan, tree[pos][1].bol);
	if(kir == kan) return;
	preorder(pos*2, kir, (kir+kan)/2);
	preorder(pos*2+1, (kir+kan)/2+1, kan);
}

int main()
{
	// ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	// freopen("input.in", "r", stdin);
	scanf("%d %d\n", &n, &q);
	for(int i = 1; i <= n; i++)
		scanf("%c", &A[i]);

	build(1, 1, n);
	// preorder(1, 1, n);
	while(q--)
	{
		int a, b;
		scanf("%d %d", &a, &b);
		update(1, 1, n, a, b);
		printf("%d\n", query(1, 1, n, a, b).mx);
		// preorder(1, 1, n);
		// return 0;
	}
}


#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <cstring>
#include <list>
#include <cassert>
#include <climits>
#include <bitset>
#include <chrono>
#include <random>
using namespace std;

#define PB push_back
#define MP make_pair
#define SZ(v) ((int)(v).size())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n) FOR(i,0,n)
#define FORE(i,a,b) for(int i=(a);i<=(b);++i)
#define REPE(i,n) FORE(i,0,n)
#define FORSZ(i,a,v) FOR(i,a,SZ(v))
#define REPSZ(i,v) REP(i,SZ(v))
std::mt19937 rnd((int)std::chrono::steady_clock::now().time_since_epoch().count());
typedef long long ll;
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }

const int MAXN = 500000;
const int MAXQ = 100000;
const int MAXS = 4 * MAXN;
struct Val { int sz, prefl, prefr, suffl, suffr, preflr, prefrl, sufflr, suffrl, insidelr, insiderl; };

int n, nq;
char s[MAXN + 1];
int ql[MAXQ], qr[MAXQ], qans[MAXQ];

Val smake(char c) {
	Val ret; ret.sz = 1, ret.preflr = ret.prefrl = ret.sufflr = ret.suffrl = ret.insidelr = ret.insiderl = 1;
	if (c == '<') ret.prefl = 1, ret.prefr = 0, ret.suffl = 1, ret.suffr = 0; else if (c == '>') ret.prefl = 0, ret.prefr = 1, ret.suffl = 0, ret.suffr = 1; else assert(false);
	return ret;
}
Val smerge(const Val& a, const Val& b) {
	Val ret; ret.sz = a.sz + b.sz;
	ret.prefl = a.prefl + (a.prefl == a.sz ? b.prefl : 0);
	ret.prefr = a.prefr + (a.prefr == a.sz ? b.prefr : 0);
	ret.suffl = b.suffl + (b.suffl == b.sz ? a.suffl : 0);
	ret.suffr = b.suffr + (b.suffr == b.sz ? a.suffr : 0);
	ret.preflr = a.preflr + (a.preflr == a.sz ? a.prefl == a.sz ? b.preflr : b.prefr : 0);
	ret.prefrl = a.prefrl + (a.prefrl == a.sz ? a.prefr == a.sz ? b.prefrl : b.prefl : 0);
	ret.sufflr = b.sufflr + (b.sufflr == b.sz ? b.suffr == b.sz ? a.sufflr : a.suffl : 0);
	ret.suffrl = b.suffrl + (b.suffrl == b.sz ? b.suffl == b.sz ? a.suffrl : a.suffr : 0);
	ret.insidelr = max(max(a.insidelr, b.insidelr), max(a.sufflr + b.prefr, a.suffl + b.preflr));
	ret.insiderl = max(max(a.insiderl, b.insiderl), max(a.suffrl + b.prefl, a.suffr + b.prefrl));
	return ret;
}
void sinvert(Val &a) {
	swap(a.prefl, a.prefr); swap(a.suffl, a.suffr); swap(a.preflr, a.prefrl); swap(a.sufflr, a.suffrl); swap(a.insidelr, a.insiderl);
}

bool slazy[MAXS];
Val sval[MAXS];

void sapply(int x) { sinvert(sval[x]); slazy[x] = !slazy[x]; }
void spush(int x) { if (slazy[x]) sapply(2 * x + 1), sapply(2 * x + 2), slazy[x] = false; }
void spull(int x) { sval[x] = smerge(sval[2 * x + 1], sval[2 * x + 2]); }
void sinit(int x, int l, int r) {
	slazy[x] = false;
	if (l == r) {
		sval[x] = smake(s[l]);
	} else {
		int m = l + (r - l) / 2;
		sinit(2 * x + 1, l, m); sinit(2 * x + 2, m + 1, r);
		spull(x);
	}
}
void stoggle(int x, int l, int r, int L, int R) {
	if (L <= l && r <= R) {
		sapply(x);
	} else {
		int m = l + (r - l) / 2; spush(x);
		if (L <= m) stoggle(2 * x + 1, l, m, L, R);
		if (m + 1 <= R) stoggle(2 * x + 2, m + 1, r, L, R);
		spull(x);
	}
}
Val sget(int x, int l, int r, int L, int R) {
	if (L <= l && r <= R) {
		return sval[x];
	} else {
		int m = l + (r - l) / 2; spush(x);
		if (L > m) return sget(2 * x + 2, m + 1, r, L, R);
		if (m + 1 > R) return sget(2 * x + 1, l, m, L, R);
		return smerge(sget(2 * x + 1, l, m, L, R), sget(2 * x + 2, m + 1, r, L, R));
	}
}

void solve() {
	sinit(0, 0, n - 1);
	REP(i, nq) {
		int l = ql[i], r = qr[i];
		stoggle(0, 0, n - 1, l, r);
		Val val = sget(0, 0, n - 1, l, r);
		qans[i] = val.insiderl;
	}
}

void run() {
	scanf("%d%d", &n, &nq);
	scanf("%s", s); assert(strlen(s) == n);
	REP(i, nq) scanf("%d%d", &ql[i], &qr[i]), --ql[i], --qr[i];
	solve();
	REP(i, nq) printf("%d\n", qans[i]);
}

int main() {
	run();
	return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define all(x) (x).begin(), (x).end()

using namespace __gnu_pbds;
using namespace std;

using ull = unsigned long long;
using ll = long long;
using ld = long double;
template <typename T> using ordered_set = tree<T, null_type, less<>, rb_tree_tag, tree_order_statistics_node_update>;

const int mod = 1e9 + 7;
const int inf = INT_MAX;
const int N = 5e5 + 5;

template <typename T> class SegmentTree {
public:
    #define F function<T(const T&, const T&)>

    int n;
    vector<T> t;
    vector<int> lazy;
    F f;
    SegmentTree() : n(), t(), f(), lazy() {}

    template <typename U> void build(const U& arr, int _n, F func = plus<T>()) {
        n = _n;
        f = move(func);
        t.resize(4 * n + 4);
        lazy.resize(4 * n + 4);
        build(arr, 1, 0, n - 1);
    }

    template <typename U> void build(const U& arr, int i, int l, int r) {
        if (l == r) {
            t[i] = T(arr[l]);
            return;
        }

        int mid = l + (r - l) / 2;
        build(arr, i << 1, l, mid);
        build(arr, i << 1 | 1, mid + 1, r);

        t[i] = f(t[i << 1], t[i << 1 | 1]);
    }

    void push (int x) {
        if (lazy[x]) {
            lazy[x] = 0;
            t[x << 1].flip();
            t[x << 1 | 1].flip();
            lazy[x << 1] ^= 1;
            lazy[x << 1 | 1] ^= 1;
        }
    }

    void update(int ql, int qr) {
        update(ql, qr, 1, 0, n - 1);
    }

    void update(int ql, int qr, int i, int l, int r) {
        if (ql > r or qr < l)
            return;
        if (ql <= l and r <= qr) {
            t[i].flip();
            lazy[i] ^= 1;
            return;
        }
        push(i);
        int mid = l + (r - l) / 2;
        update(ql, qr, i << 1, l, mid);
        update(ql, qr, i << 1 | 1, mid + 1, r);

        t[i] = f(t[i << 1], t[i << 1 | 1]);
    }

    T query(int ql, int qr) {
        return query(ql, qr, 1, 0, n - 1);
    }

    T query(int ql, int qr, int i, int l, int r) {
        if (ql > r or qr < l)
            return T();
        if (l >= ql and r <= qr)
            return t[i];
        push(i);
        int mid = l + (r - l) / 2;
        T x = query(ql, qr, i << 1, l, mid), y = query(ql, qr, i << 1 | 1, mid + 1, r);
        return f(x, y);
    }
};

int n, q;

struct node {
    int len, first, last, prefi, prefd, sufi, sufd, besti, bestd;
    node(): len(), first(), last(), prefi(), prefd(), sufi(), sufd(), besti(), bestd() {}
    node(char c): len(1), first(c == '<'), last(c == '<'), prefi(1), prefd(1), sufi(1), sufd(1), besti(1), bestd(1) {}

    void flip() {
        first = 1 - first;
        last = 1 - last;
        swap(prefi, prefd);
        swap(sufi, sufd);
        swap(besti, bestd);
    }
};

node combine(const node& x, const node& y) {
    if (!x.len)
        return y;
    if (!y.len)
        return x;

    node ans;
    ans.len = x.len + y.len;
    ans.first = x.first;
    ans.last = y.last;

    ans.besti = max(x.besti, y.besti);
    ans.bestd = max(x.bestd, y.bestd);

    ans.prefi = x.prefi; ans.prefd = x.prefd;
    ans.sufi = y.sufi; ans.sufd = y.sufd;

    if (x.last <= y.first) {
        ans.besti = max(ans.besti, x.sufi + y.prefi);
        if (x.prefi == x.len)
            ans.prefi = max(ans.prefi, x.len + y.prefi);
        if (y.prefi == y.len)
            ans.sufi = max(ans.sufd, x.sufi + y.len);
    }
    if (x.last >= y.first) {
        ans.bestd = max(ans.bestd, x.sufd + y.prefd);
        if (x.prefd == x.len)
            ans.prefd = max(ans.prefd, x.len + y.prefd);
        if (y.prefd == y.len)
            ans.sufd = max(ans.sufd, x.sufd + y.len);
    }
    return ans;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n >> q;
    string s; cin >> s;

    SegmentTree<node> st;
    st.build(s, n, combine);

    while (q--) {
        int l, r;
        cin >> l >> r; --l; --r;
        st.update(l, r);
        cout << st.query(l, r).besti << "\n";
    }
    return 0;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define all(x) (x).begin(), (x).end()

using namespace __gnu_pbds;
using namespace std;

using ull = unsigned long long;
using ll = long long;
using ld = long double;
template <typename T> using ordered_set = tree<T, null_type, less<>, rb_tree_tag, tree_order_statistics_node_update>;

const int mod = 1e9 + 7;
const int inf = INT_MAX;
const int N = 5e5 + 5;

template <typename T> class SegmentTree {
public:
    #define F function<T(const T&, const T&)>

    int n;
    vector<T> t;
    vector<int> lazy;
    F f;
    SegmentTree() : n(), t(), f(), lazy() {}

    template <typename U> void build(const U& arr, int _n, F func = plus<T>()) {
        n = _n;
        f = move(func);
        t.resize(4 * n + 4);
        lazy.resize(4 * n + 4);
        build(arr, 1, 0, n - 1);
    }

    template <typename U> void build(const U& arr, int i, int l, int r) {
        if (l == r) {
            t[i] = T(arr[l]);
            return;
        }

        int mid = l + (r - l) / 2;
        build(arr, i << 1, l, mid);
        build(arr, i << 1 | 1, mid + 1, r);

        t[i] = f(t[i << 1], t[i << 1 | 1]);
    }

    void push (int x) {
        if (lazy[x]) {
            lazy[x] = 0;
            t[x << 1].flip();
            t[x << 1 | 1].flip();
            lazy[x << 1] ^= 1;
            lazy[x << 1 | 1] ^= 1;
        }
    }

    void update(int ql, int qr) {
        update(ql, qr, 1, 0, n - 1);
    }

    void update(int ql, int qr, int i, int l, int r) {
        if (ql > r or qr < l)
            return;
        if (ql <= l and r <= qr) {
            t[i].flip();
            lazy[i] ^= 1;
            return;
        }
        push(i);
        int mid = l + (r - l) / 2;
        update(ql, qr, i << 1, l, mid);
        update(ql, qr, i << 1 | 1, mid + 1, r);

        t[i] = f(t[i << 1], t[i << 1 | 1]);
    }

    T query(int ql, int qr) {
        return query(ql, qr, 1, 0, n - 1);
    }

    T query(int ql, int qr, int i, int l, int r) {
        if (ql > r or qr < l)
            return T();
        if (l >= ql and r <= qr)
            return t[i];
        push(i);
        int mid = l + (r - l) / 2;
        T x = query(ql, qr, i << 1, l, mid), y = query(ql, qr, i << 1 | 1, mid + 1, r);
        return f(x, y);
    }
};

int n, a[N], q;

struct node {
    int len, first, last, prefi, prefd, sufi, sufd, besti, bestd;
    node(): len(), first(), last(), prefi(), prefd(), sufi(), sufd(), besti(), bestd() {}
    node(int x): len(1), first(x), last(x), prefi(1), prefd(1), sufi(1), sufd(1), besti(1), bestd(1) {}

    void flip() {
        first = 1 - first;
        last = 1 - last;
        swap(prefi, prefd);
        swap(sufi, sufd);
        swap(besti, bestd);
    }
};

node combine(const node& x, const node& y) {
    if (!x.len)
        return y;
    if (!y.len)
        return x;

    node ans;
    ans.len = x.len + y.len;
    ans.first = x.first;
    ans.last = y.last;

    ans.besti = max(x.besti, y.besti);
    ans.bestd = max(x.bestd, y.bestd);

    ans.prefi = x.prefi; ans.prefd = x.prefd;
    ans.sufi = y.sufi; ans.sufd = y.sufd;

    if (x.last <= y.first) {
        ans.besti = max(ans.besti, x.sufi + y.prefi);
        if (x.prefi == x.len)
            ans.prefi = max(ans.prefi, x.len + y.prefi);
        if (y.prefi == y.len)
            ans.sufi = max(ans.sufd, x.sufi + y.len);
    }
    if (x.last >= y.last) {
        ans.bestd = max(ans.bestd, x.sufd + y.prefd);
        if (x.prefd == x.len)
            ans.prefd = max(ans.prefd, x.len + y.prefd);
        if (y.prefd == y.len)
            ans.sufd = max(ans.sufd, x.sufd + y.len);
    }
    return ans;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n >> q;
    string s; cin >> s;

    for (int i = 0; i < n; i++)
        a[i] = (s[i] == '<');

    SegmentTree<node> st;
    st.build(a, n, combine);

    while (q--) {
        int l, r;
        cin >> l >> r; --l; --r;
        st.update(l, r);
        cout << st.query(l, r).besti << "\n";
    }
    return 0;
}


#include <algorithm>
#include <ctime>
#include <iostream>
using namespace std;
#define leftnode (node<<1)
#define rightnode ((node<<1)|1)
#define getmid ((left+right)>>1)

const int MAXN = 5e3 + 10;
struct Item{
  int head = -1;
  int len = 0;
  int type[2] = {};
  int in = 0;
  int cnt[2] = {};
  Item() = default;
  Item(int h) {
    head = h;
    len = 1;
    type[1-h] = 1;
    cnt[1-h] = 1;
  }
};

string s;
Item tree[MAXN<<2][2];
int idx[MAXN<<2], info[MAXN<<2];

Item merge(const Item& x, const Item& y) {
  if (x.head == -1) return y;
  if (y.head == -1) return x;
  Item ret;
  ret.head = x.head;
  ret.len = x.len + y.len;
  if ((x.head+x.len-1)%2 == y.head) ret.len--;
  ret.in = max(x.in, y.in);
  if (x.type[0] == 0 && x.type[1] == 1) {
    if (y.type[0] == 0 && y.type[1] == 1) {
      ret.type[1] = 1;
      ret.cnt[1] = x.cnt[1] + y.cnt[1];
    } else if (y.type[1] == 0) {
      ret.type[0] = 2;
      ret.cnt[0] = x.cnt[1] + y.cnt[0];
    } else {
      ret.type[0] = 2;
      ret.type[1] = y.type[1];
      ret.cnt[0] = x.cnt[1] + y.cnt[0];
      ret.cnt[1] = y.cnt[1];
    }
    return ret;
  }
  if (x.type[0] == 1 && x.type[1] == 0) {
    if (y.type[0] == 0 || y.type[0] == 1) {
      ret.type[0] = 1;
      ret.type[1] = y.type[1];
      ret.cnt[0] = x.cnt[0] + y.cnt[0];
      ret.cnt[1] = y.cnt[1];
    } else if (y.type[1] == 0) {
      ret.type[0] = 1;
      ret.type[1] = 2;
      ret.cnt[0] = x.cnt[0];
      ret.cnt[1] = y.cnt[0];
    } else {
      ret.type[0] = 1;
      ret.type[1] = y.type[1];
      ret.in = max(ret.in, y.cnt[0]);
      ret.cnt[0] = x.cnt[0];
      ret.cnt[1] = y.cnt[1];
    }
    return ret;
  }
  if (x.type[0] == 2 && x.type[1] == 0 && y.type[0] == 2 && y.type[1] == 0) {
    ret.type[0] = 2;
    ret.type[1] = 2;
    ret.cnt[0] = x.cnt[0];
    ret.cnt[1] = y.cnt[0];
    return ret;
  }
  if (x.type[0] == 2 && x.type[1] == 0 && y.type[0] == 1) {
    ret.type[0] = 2;
    ret.type[1] = y.type[1];
    ret.cnt[0] = x.cnt[0] + y.cnt[0];
    ret.cnt[1] = y.cnt[1];
    return ret;
  }
  if (y.type[0] == 0 && x.type[1] == 1) {
    ret.type[0] = x.type[0];
    ret.type[1] = 1;
    ret.cnt[0] = x.cnt[0];
    ret.cnt[1] = x.cnt[1] + y.cnt[1];
    return ret;
  }
  ret.type[0] = x.type[0];
  ret.type[1] = y.type[1];
  ret.cnt[0] = x.cnt[0];
  ret.cnt[1] = y.cnt[1];
  if (x.type[1] == 2 && y.type[0] == 2) {
    ret.in = max(ret.in, x.cnt[1]);
    ret.in = max(ret.in, y.cnt[0]);
  } else ret.in = max(ret.in, x.cnt[1] + y.cnt[0]);
  return ret;
}

void build(int node, int left, int right) {
  if (left == right) {
    if (s[left-1] == '>') {
      tree[node][0] = Item(0);
      tree[node][1] = Item(1);
    } else {
      tree[node][0] = Item(1);
      tree[node][1] = Item(0);
    }
    return;
  }
  int mid = getmid;
  build (leftnode, left, mid);
  build (rightnode, mid+1, right);
  tree[node][0] = merge(tree[leftnode][0], tree[rightnode][0]);
  tree[node][1] = merge(tree[leftnode][1], tree[rightnode][1]);
}

void push_down(int node, int left, int right) {
  if (left == right || info[node] == 0) return;
  idx[leftnode] ^= 1;
  idx[rightnode] ^= 1;
  info[leftnode] ^= 1;
  info[rightnode] ^= 1;
  info[node] = 0;
}

void update(int node, int left, int right, int i, int j) {
  if (right < i || j < left) return;
  if (i <= left && right <= j) {
    info[node] ^= 1;
    idx[node] ^= 1;
    return;
  }
  push_down(node, left, right);
  int mid = getmid;
  update(leftnode, left, mid, i, j);
  update(rightnode, mid+1, right, i, j);
  tree[node][idx[node]] = merge(tree[leftnode][idx[leftnode]], tree[rightnode][idx[rightnode]]);
  tree[node][idx[node]^1] = merge(tree[leftnode][idx[leftnode]^1], tree[rightnode][idx[rightnode]^1]);
}

Item query(int node, int left, int right, int i, int j) {
  if (right < i || j < left) return Item();
  if (i <= left && right <= j) {
    return tree[node][idx[node]];
  }
  push_down(node, left, right);
  int mid = getmid;
  Item a = query(leftnode, left, mid, i, j);
  Item b = query(rightnode, mid+1, right, i, j);
  return merge(a, b);
}

int main() {
  ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
  cout.precision(10); cout << fixed;
#ifdef LOCAL
  freopen("../test.txt", "r", stdin);
#endif
  int n, q; cin >> n >> q;
  cin >> s;
  build (1, 1, n);
  while (q--) {
    int a, b; cin >> a >> b;
    update(1, 1, n, a, b);
    Item tmp = query(1, 1, n, a, b);
    int ret = max(tmp.cnt[0], tmp.cnt[1]);
    ret = max(ret, tmp.in);
    cout << ret << '\n';
  }
  return 0;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <ctime>
#include <deque>
#include <iostream>
#include <list>
#include <map>
#include <memory.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>
using namespace std;
typedef long double LD;
typedef long long LL;
typedef pair<LL, LL> pll;
typedef pair<int, int> pii;
typedef vector<int> vi;
#ifdef LOCAL
#define DEBUG(x) { cerr << "# " << #x << ": " << x << endl;}
#else
#define DEBUG(x)
#endif
mt19937_64 mt(time(0));
/*---------------------------------------------------------------------------------------------------
　　　　　　　　　　　 ∧＿∧
　　　　　 ∧＿∧ 　（´<_｀ ）　 Welcome to My Coding Space!
　　　　 （ ´_ゝ`）　/　 ⌒i
　　　　／　　　＼　 　  |　|
　　　 /　　 /￣￣￣￣/　　|
　 ＿_(__ﾆつ/　    ＿/ .| .|＿＿＿＿
　 　　　＼/＿＿＿＿/　（u　⊃
---------------------------------------------------------------------------------------------------*/
#define leftnode (node<<1)
#define rightnode ((node<<1)|1)
#define getmid ((left+right)>>1)

const int MAXN = 5e5 + 10;
struct Item{
  bool head;
  int len = 0;
  int8_t type[2] = {};
  int in = 0;
  int cnt[2] = {};
  Item() = default;
  Item(int h) {
    head = h;
    len = 1;
    type[1-h] = 1;
    cnt[1-h] = 1;
  }
};

string s;
Item tree[MAXN<<2][2];
int idx[MAXN<<2], info[MAXN<<2];

Item merge(const Item& x, const Item& y) {
  if (x.len == 0) return y;
  if (y.len == 0) return x;
  Item ret;
  ret.head = x.head;
  ret.len = x.len + y.len;
  if ((x.head+x.len-1)%2 == y.head) ret.len--;
  ret.in = max(x.in, y.in);

  if (x.type[0] == 0 && x.type[1] == 1) {
    if (y.type[0] == 0 && y.type[1] == 1) {
      ret.type[1] = 1;
      ret.cnt[1] = x.cnt[1] + y.cnt[1];
    } else if (y.type[1] == 0) {
      ret.type[0] = 2;
      ret.cnt[0] = x.cnt[1] + y.cnt[0];
    } else {
      ret.type[0] = 2;
      ret.type[1] = y.type[1];
      ret.cnt[0] = x.cnt[1] + y.cnt[0];
      ret.cnt[1] = y.cnt[1];
    }
    return ret;
  }
  if (x.type[0] == 1 && x.type[1] == 0) {
    if (y.type[0] == 0 || y.type[0] == 1) {
      ret.type[0] = 1;
      ret.type[1] = y.type[1];
      ret.cnt[0] = x.cnt[0] + y.cnt[0];
      ret.cnt[1] = y.cnt[1];
    } else if (y.type[1] == 0) {
      ret.type[0] = 1;
      ret.type[1] = 2;
      ret.cnt[0] = x.cnt[0];
      ret.cnt[1] = y.cnt[0];
    } else {
      ret.type[0] = 1;
      ret.type[1] = y.type[1];
      ret.in = max(ret.in, y.cnt[0]);
      ret.cnt[0] = x.cnt[0];
      ret.cnt[1] = y.cnt[1];
    }
    return ret;
  }
  if (x.type[0] == 2 && x.type[1] == 0 && y.type[0] == 2 && y.type[1] == 0) {
    ret.type[0] = 2;
    ret.type[1] = 2;
    ret.cnt[0] = x.cnt[0];
    ret.cnt[1] = y.cnt[0];
    return ret;
  }
  if (x.type[0] == 2 && x.type[1] == 0 && y.type[0] == 1) {
    ret.type[0] = 2;
    ret.type[1] = y.type[1];
    ret.cnt[0] = x.cnt[0] + y.cnt[0];
    ret.cnt[1] = y.cnt[1];
    return ret;
  }
  if (y.type[0] == 0 && x.type[1] == 1) {
    ret.type[0] = x.type[0];
    ret.type[1] = 1;
    ret.cnt[0] = x.cnt[0];
    ret.cnt[1] = x.cnt[1] + y.cnt[1];
    return ret;
  }
  if (y.type[0] == 1 && y.type[1] == 0) {
    ret.type[0] = x.type[0];
    ret.type[1] = 2;
    ret.cnt[0] = x.cnt[0];
    ret.cnt[1] = x.cnt[1] + y.cnt[0];
    return ret;
  }
  if (y.type[0] == 2 && y.type[1] == 0) {
    if (x.type[1] == 1) {
      ret.type[0] = x.type[0];
      ret.type[1] = 2;
      ret.cnt[0] = x.cnt[0];
      ret.cnt[1] = x.cnt[1] + y.cnt[0];
    } else {
      ret.type[0] = x.type[0];
      ret.type[1] = 2;
      ret.in = max(ret.in, x.cnt[1]);
      ret.cnt[0] = x.cnt[0];
      ret.cnt[1] = y.cnt[0];
    }
    return ret;
  }
  ret.type[0] = x.type[0];
  ret.type[1] = y.type[1];
  ret.cnt[0] = x.cnt[0];
  ret.cnt[1] = y.cnt[1];
  if (x.type[1] == 2 && y.type[0] == 2) {
    ret.in = max(ret.in, x.cnt[1]);
    ret.in = max(ret.in, y.cnt[0]);
  } else ret.in = max(ret.in, x.cnt[1] + y.cnt[0]);
  return ret;
}

void build(int node, int left, int right) {
  if (left == right) {
    if (s[left-1] == '>') {
      tree[node][0] = Item(0);
      tree[node][1] = Item(1);
    } else {
      tree[node][0] = Item(1);
      tree[node][1] = Item(0);
    }
    return;
  }
  int mid = getmid;
  build (leftnode, left, mid);
  build (rightnode, mid+1, right);
  tree[node][0] = merge(tree[leftnode][0], tree[rightnode][0]);
  tree[node][1] = merge(tree[leftnode][1], tree[rightnode][1]);
}

void push_down(int node, int left, int right) {
  if (left == right || info[node] == 0) return;
  idx[leftnode] ^= 1;
  idx[rightnode] ^= 1;
  info[leftnode] ^= 1;
  info[rightnode] ^= 1;
  info[node] = 0;
}

void update(int node, int left, int right, int i, int j) {
  if (right < i || j < left) return;
  if (i <= left && right <= j) {
    info[node] ^= 1;
    idx[node] ^= 1;
    return;
  }
  push_down(node, left, right);
  int mid = getmid;
  update(leftnode, left, mid, i, j);
  update(rightnode, mid+1, right, i, j);
  tree[node][idx[node]] = merge(tree[leftnode][idx[leftnode]], tree[rightnode][idx[rightnode]]);
  tree[node][idx[node]^1] = merge(tree[leftnode][idx[leftnode]^1], tree[rightnode][idx[rightnode]^1]);
}

Item query(int node, int left, int right, int i, int j) {
  if (right < i || j < left) return Item();
  if (i <= left && right <= j) {
    return tree[node][idx[node]];
  }
  push_down(node, left, right);
  int mid = getmid;
  Item a = query(leftnode, left, mid, i, j);
  Item b = query(rightnode, mid+1, right, i, j);
  return merge(a, b);
}

void dfs() {
  if (s.size() > 5) return;
  if (!s.empty()) {
    build (1, 1, s.size());
    auto item = query(1, 1, s.size(), 1, s.size());
    cout << s << endl;
    cout << "head: " << item.head << ' ' << "len: " << item.len << ' ' << "in: " << item.in << endl;
    cout << "type: " << (int)item.type[0] << ' ' << (int)item.type[1] << endl;
    cout << "cnt: " << item.cnt[0] << ' ' << item.cnt[1] << endl;
  }
  s.push_back('>');
  dfs();
  s.pop_back();
  s.push_back('<');
  dfs();
  s.pop_back();
}
int main() {
  ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
  cout.precision(10); cout << fixed;
#ifdef LOCAL
  freopen("../test.txt", "r", stdin);
  // freopen("../output.txt", "w", stdout);
#endif
//  dfs();
//s = "><>><";
//int n = s.size();
//build (1, 1, n);
//auto item = query(1, 1, n, 1, n);
//n++;
  int n, q; cin >> n >> q;
  cin >> s;
  build (1, 1, n);
  while (q--) {
    int a, b; cin >> a >> b;
    update(1, 1, n, a, b);
    Item tmp = query(1, 1, n, a, b);
    int ret = max(tmp.cnt[0], tmp.cnt[1]);
    ret = max(ret, tmp.in);
    cout << ret << '\n';
  }

/*---------------------------------------Coding Space End------------------------------------------*/
#ifdef LOCAL
  cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s." << endl;
#endif
  return 0;
}
/* author:  txingml */
/* picture is from hamayanhamayan(CF handle) */


#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <ctime>
#include <deque>
#include <iostream>
#include <list>
#include <map>
#include <memory.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>
using namespace std;
typedef long double LD;
typedef long long LL;
typedef pair<LL, LL> pll;
typedef pair<int, int> pii;
typedef vector<int> vi;
#ifdef LOCAL
#define DEBUG(x) { cerr << "# " << #x << ": " << x << endl;}
#else
#define DEBUG(x)
#endif
mt19937_64 mt(time(0));
/*---------------------------------------------------------------------------------------------------
　　　　　　　　　　　 ∧＿∧
　　　　　 ∧＿∧ 　（´<_｀ ）　 Welcome to My Coding Space!
　　　　 （ ´_ゝ`）　/　 ⌒i
　　　　／　　　＼　 　  |　|
　　　 /　　 /￣￣￣￣/　　|
　 ＿_(__ﾆつ/　    ＿/ .| .|＿＿＿＿
　 　　　＼/＿＿＿＿/　（u　⊃
---------------------------------------------------------------------------------------------------*/
#define leftnode (node<<1)
#define rightnode ((node<<1)|1)
#define getmid ((left+right)>>1)

const int MAXN = 5e5 + 10;
struct Item{
  bool head;
  int len = 0;
  int8_t type[2] = {};
  int in = 0;
  int cnt[2] = {};
  Item() = default;
  Item(int h) {
    head = h;
    len = 1;
    type[1-h] = 1;
    cnt[1-h] = 1;
  }
};

string s;
Item tree[MAXN<<2][2];
int idx[MAXN<<2], info[MAXN<<2];

Item merge(const Item& x, const Item& y) {
  if (x.len == 0) return y;
  if (y.len == 0) return x;
  Item ret;
  ret.head = x.head;
  ret.len = x.len + y.len;
  if ((x.head+x.len-1)%2 == y.head) ret.len--;
  ret.in = max(x.in, y.in);
  if (x.type[0] == 0 && x.type[1] == 1) {
    if (y.type[0] == 0 && y.type[1] == 1) {
      ret.type[1] = 1;
      ret.cnt[1] = x.cnt[1] + y.cnt[1];
    } else if (y.type[1] == 0) {
      ret.type[0] = 2;
      ret.cnt[0] = x.cnt[1] + y.cnt[0];
    } else {
      ret.type[0] = 2;
      ret.type[1] = y.type[1];
      ret.cnt[0] = x.cnt[1] + y.cnt[0];
      ret.cnt[1] = y.cnt[1];
    }
    return ret;
  }
  if (x.type[0] == 1 && x.type[1] == 0) {
    if (y.type[0] == 0 || y.type[0] == 1) {
      ret.type[0] = 1;
      ret.type[1] = y.type[1];
      ret.cnt[0] = x.cnt[0] + y.cnt[0];
      ret.cnt[1] = y.cnt[1];
    } else if (y.type[1] == 0) {
      ret.type[0] = 1;
      ret.type[1] = 2;
      ret.cnt[0] = x.cnt[0];
      ret.cnt[1] = y.cnt[0];
    } else {
      ret.type[0] = 1;
      ret.type[1] = y.type[1];
      ret.in = max(ret.in, y.cnt[0]);
      ret.cnt[0] = x.cnt[0];
      ret.cnt[1] = y.cnt[1];
    }
    return ret;
  }
  if (x.type[0] == 2 && x.type[1] == 0 && y.type[0] == 2 && y.type[1] == 0) {
    ret.type[0] = 2;
    ret.type[1] = 2;
    ret.cnt[0] = x.cnt[0];
    ret.cnt[1] = y.cnt[0];
    return ret;
  }
  if (x.type[0] == 2 && x.type[1] == 0 && y.type[0] == 1) {
    ret.type[0] = 2;
    ret.type[1] = y.type[1];
    ret.cnt[0] = x.cnt[0] + y.cnt[0];
    ret.cnt[1] = y.cnt[1];
    return ret;
  }
  if (y.type[0] == 0 && x.type[1] == 1) {
    ret.type[0] = x.type[0];
    ret.type[1] = 1;
    ret.cnt[0] = x.cnt[0];
    ret.cnt[1] = x.cnt[1] + y.cnt[1];
    return ret;
  }
  ret.type[0] = x.type[0];
  ret.type[1] = y.type[1];
  ret.cnt[0] = x.cnt[0];
  ret.cnt[1] = y.cnt[1];
  if (x.type[1] == 2 && y.type[0] == 2) {
    ret.in = max(ret.in, x.cnt[1]);
    ret.in = max(ret.in, y.cnt[0]);
  } else ret.in = max(ret.in, x.cnt[1] + y.cnt[0]);
  return ret;
}

void build(int node, int left, int right) {
  if (left == right) {
    if (s[left-1] == '>') {
      tree[node][0] = Item(0);
      tree[node][1] = Item(1);
    } else {
      tree[node][0] = Item(1);
      tree[node][1] = Item(0);
    }
    return;
  }
  int mid = getmid;
  build (leftnode, left, mid);
  build (rightnode, mid+1, right);
  tree[node][0] = merge(tree[leftnode][0], tree[rightnode][0]);
  tree[node][1] = merge(tree[leftnode][1], tree[rightnode][1]);
}

void push_down(int node, int left, int right) {
  if (left == right || info[node] == 0) return;
  idx[leftnode] ^= 1;
  idx[rightnode] ^= 1;
  info[leftnode] ^= 1;
  info[rightnode] ^= 1;
  info[node] = 0;
}

void update(int node, int left, int right, int i, int j) {
  if (right < i || j < left) return;
  if (i <= left && right <= j) {
    info[node] ^= 1;
    idx[node] ^= 1;
    return;
  }
  push_down(node, left, right);
  int mid = getmid;
  update(leftnode, left, mid, i, j);
  update(rightnode, mid+1, right, i, j);
  tree[node][idx[node]] = merge(tree[leftnode][idx[leftnode]], tree[rightnode][idx[rightnode]]);
  tree[node][idx[node]^1] = merge(tree[leftnode][idx[leftnode]^1], tree[rightnode][idx[rightnode]^1]);
}

Item query(int node, int left, int right, int i, int j) {
  if (right < i || j < left) return Item();
  if (i <= left && right <= j) {
    return tree[node][idx[node]];
  }
  push_down(node, left, right);
  int mid = getmid;
  Item a = query(leftnode, left, mid, i, j);
  Item b = query(rightnode, mid+1, right, i, j);
  return merge(a, b);
}

int main() {
  ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
  cout.precision(10); cout << fixed;
#ifdef LOCAL
  freopen("../test.txt", "r", stdin);
  // freopen("../output.txt", "w", stdout);
#endif
  int n, q; cin >> n >> q;
  cin >> s;
  build (1, 1, n);
  while (q--) {
    int a, b; cin >> a >> b;
    update(1, 1, n, a, b);
    Item tmp = query(1, 1, n, a, b);
    int ret = max(tmp.cnt[0], tmp.cnt[1]);
    ret = max(ret, tmp.in);
    cout << ret << '\n';
  }

/*---------------------------------------Coding Space End------------------------------------------*/
#ifdef LOCAL
  cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s." << endl;
#endif
  return 0;
}
/* author:  txingml */
/* picture is from hamayanhamayan(CF handle) */


#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <ctime>
#include <deque>
#include <iostream>
#include <list>
#include <map>
#include <memory.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>
using namespace std;
typedef long double LD;
typedef long long LL;
typedef pair<LL, LL> pll;
typedef pair<int, int> pii;
typedef vector<int> vi;
#ifdef LOCAL
#define DEBUG(x) { cerr << "# " << #x << ": " << x << endl;}
#else
#define DEBUG(x)
#endif
mt19937_64 mt(time(0));
/*---------------------------------------------------------------------------------------------------
　　　　　　　　　　　 ∧＿∧
　　　　　 ∧＿∧ 　（´<_｀ ）　 Welcome to My Coding Space!
　　　　 （ ´_ゝ`）　/　 ⌒i
　　　　／　　　＼　 　  |　|
　　　 /　　 /￣￣￣￣/　　|
　 ＿_(__ﾆつ/　    ＿/ .| .|＿＿＿＿
　 　　　＼/＿＿＿＿/　（u　⊃
---------------------------------------------------------------------------------------------------*/
#define leftnode (node<<1)
#define rightnode ((node<<1)|1)
#define getmid ((left+right)>>1)

const int MAXN = 5e5 + 10;
struct Item{
  bool head;
  int len = 0;
  int8_t type[2] = {};
  int in = 0;
  int cnt[2] = {};
  Item() = default;
  Item(int h) {
    head = h;
    len = 1;
    type[1-h] = 1;
    cnt[1-h] = 1;
  }
};

string s;
Item tree[MAXN<<2][2];
int idx[MAXN<<2], info[MAXN<<2];

Item merge(const Item& x, const Item& y) {
  if (x.len == 0) return y;
  if (y.len == 0) return x;
  Item ret;
  ret.head = x.head;
  ret.len = x.len + y.len;
  if ((x.head+x.len-1)%2 == y.head) ret.len--;
  ret.in = max(x.in, y.in);

  if (x.type[0] == 0 && x.type[1] == 1) {
    if (y.type[0] == 0 && y.type[1] == 1) {
      ret.type[1] = 1;
      ret.cnt[1] = x.cnt[1] + y.cnt[1];
    } else if (y.type[1] == 0) {
      ret.type[0] = 2;
      ret.cnt[0] = x.cnt[1] + y.cnt[0];
    } else {
      ret.type[0] = 2;
      ret.type[1] = y.type[1];
      ret.cnt[0] = x.cnt[1] + y.cnt[0];
      ret.cnt[1] = y.cnt[1];
    }
    return ret;
  }
  if (x.type[0] == 1 && x.type[1] == 0) {
    if (y.type[0] == 0 || y.type[0] == 1) {
      ret.type[0] = 1;
      ret.type[1] = y.type[1];
      ret.cnt[0] = x.cnt[0] + y.cnt[0];
      ret.cnt[1] = y.cnt[1];
    } else if (y.type[1] == 0) {
      ret.type[0] = 1;
      ret.type[1] = 2;
      ret.cnt[0] = x.cnt[0];
      ret.cnt[1] = y.cnt[0];
    } else {
      ret.type[0] = 1;
      ret.type[1] = y.type[1];
      ret.in = max(ret.in, y.cnt[0]);
      ret.cnt[0] = x.cnt[0];
      ret.cnt[1] = y.cnt[1];
    }
    return ret;
  }
  if (x.type[0] == 2 && x.type[1] == 0 && y.type[0] == 2 && y.type[1] == 0) {
    ret.type[0] = 2;
    ret.type[1] = 2;
    ret.cnt[0] = x.cnt[0];
    ret.cnt[1] = y.cnt[0];
    return ret;
  }
  if (x.type[0] == 2 && x.type[1] == 0 && y.type[0] == 1) {
    ret.type[0] = 2;
    ret.type[1] = y.type[1];
    ret.cnt[0] = x.cnt[0] + y.cnt[0];
    ret.cnt[1] = y.cnt[1];
    return ret;
  }
  if (y.type[0] == 0 && x.type[1] == 1) {
    ret.type[0] = x.type[0];
    ret.type[1] = 1;
    ret.cnt[0] = x.cnt[0];
    ret.cnt[1] = x.cnt[1] + y.cnt[1];
    return ret;
  }
  if (y.type[0] == 1 && y.type[1] == 0) {
    ret.type[0] = x.type[0];
    ret.type[1] = 2;
    ret.cnt[0] = x.cnt[0];
    ret.cnt[1] = x.cnt[1] + y.cnt[0];
    return ret;
  }
  if (y.type[0] == 2 && y.type[1] == 0) {
    if (x.type[1] == 1) {
      ret.type[0] = x.type[0];
      ret.type[1] = 2;
      ret.cnt[0] = x.cnt[0];
      ret.cnt[1] = x.cnt[1] + y.cnt[0];
    } else {
      ret.type[0] = x.type[0];
      ret.type[1] = 2;
      ret.in = max(ret.in, x.cnt[1]);
      ret.cnt[0] = x.cnt[0];
      ret.cnt[1] = y.cnt[0];
    }
    return ret;
  }
  ret.type[0] = x.type[0];
  ret.type[1] = y.type[1];
  ret.cnt[0] = x.cnt[0];
  ret.cnt[1] = y.cnt[1];
  if (x.type[1] == 2 && y.type[0] == 2) {
    ret.in = max(ret.in, x.cnt[1]);
    ret.in = max(ret.in, y.cnt[0]);
  } else ret.in = max(ret.in, x.cnt[1] + y.cnt[0]);
  return ret;
}

void build(int node, int left, int right) {
  if (left == right) {
    if (s[left-1] == '>') {
      tree[node][0] = Item(0);
      tree[node][1] = Item(1);
    } else {
      tree[node][0] = Item(1);
      tree[node][1] = Item(0);
    }
    return;
  }
  int mid = getmid;
  build (leftnode, left, mid);
  build (rightnode, mid+1, right);
  tree[node][0] = merge(tree[leftnode][0], tree[rightnode][0]);
  tree[node][1] = merge(tree[leftnode][1], tree[rightnode][1]);
}

void push_down(int node, int left, int right) {
  if (left == right || info[node] == 0) return;
  idx[leftnode] ^= 1;
  idx[rightnode] ^= 1;
  info[leftnode] ^= 1;
  info[rightnode] ^= 1;
  info[node] = 0;
}

void update(int node, int left, int right, int i, int j) {
  if (right < i || j < left) return;
  if (i <= left && right <= j) {
    info[node] ^= 1;
    idx[node] ^= 1;
    return;
  }
  push_down(node, left, right);
  int mid = getmid;
  update(leftnode, left, mid, i, j);
  update(rightnode, mid+1, right, i, j);
  tree[node][idx[node]] = merge(tree[leftnode][idx[leftnode]], tree[rightnode][idx[rightnode]]);
  tree[node][idx[node]^1] = merge(tree[leftnode][idx[leftnode]^1], tree[rightnode][idx[rightnode]^1]);
}

Item query(int node, int left, int right, int i, int j) {
  if (right < i || j < left) return Item();
  if (i <= left && right <= j) {
    return tree[node][idx[node]];
  }
  push_down(node, left, right);
  int mid = getmid;
  Item a = query(leftnode, left, mid, i, j);
  Item b = query(rightnode, mid+1, right, i, j);
  return merge(a, b);
}

int main() {
  ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
  cout.precision(10); cout << fixed;
#ifdef LOCAL
  freopen("../test.txt", "r", stdin);
  // freopen("../output.txt", "w", stdout);
#endif
  int n, q; cin >> n >> q;
  cin >> s;
  build (1, 1, n);
  while (q--) {
    int a, b; cin >> a >> b;
    update(1, 1, n, a, b);
    Item tmp = query(1, 1, n, a, b);
    int ret = max(tmp.cnt[0], tmp.cnt[1]);
    ret = max(ret, tmp.in);
    cout << ret << '\n';
  }

/*---------------------------------------Coding Space End------------------------------------------*/
#ifdef LOCAL
  cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s." << endl;
#endif
  return 0;
}
/* author:  txingml */
/* picture is from hamayanhamayan(CF handle) */


#include <algorithm>
#include <ctime>
#include <iostream>
using namespace std;
#define leftnode (node<<1)
#define rightnode ((node<<1)|1)
#define getmid ((left+right)>>1)

const int MAXN = 5e5 + 10;
struct Item{
  int head = -1;
  int len = 0;
  int type[2] = {};
  int in = 0;
  int cnt[2] = {};
  Item() = default;
  Item(int h) {
    head = h;
    len = 1;
    type[1-h] = 1;
    cnt[1-h] = 1;
  }
};

string s;
Item tree[MAXN<<2][2];
int idx[MAXN<<2], info[MAXN<<2];

Item merge(const Item& x, const Item& y) {
  if (x.head == -1) return y;
  if (y.head == -1) return x;
  Item ret;
  ret.head = x.head;
  ret.len = x.len + y.len;
  if ((x.head+x.len-1)%2 == y.head) ret.len--;
  ret.in = max(x.in, y.in);
  if (x.type[0] == 0 && x.type[1] == 1) {
    if (y.type[0] == 0 && y.type[1] == 1) {
      ret.type[1] = 1;
      ret.cnt[1] = x.cnt[1] + y.cnt[1];
    } else if (y.type[1] == 0) {
      ret.type[0] = 2;
      ret.cnt[0] = x.cnt[1] + y.cnt[0];
    } else {
      ret.type[0] = 2;
      ret.type[1] = y.type[1];
      ret.cnt[0] = x.cnt[1] + y.cnt[0];
      ret.cnt[1] = y.cnt[1];
    }
    return ret;
  }
  if (x.type[0] == 1 && x.type[1] == 0) {
    if (y.type[0] == 0 || y.type[0] == 1) {
      ret.type[0] = 1;
      ret.type[1] = y.type[1];
      ret.cnt[0] = x.cnt[0] + y.cnt[0];
      ret.cnt[1] = y.cnt[1];
    } else if (y.type[1] == 0) {
      ret.type[0] = 1;
      ret.type[1] = 2;
      ret.cnt[0] = x.cnt[0];
      ret.cnt[1] = y.cnt[0];
    } else {
      ret.type[0] = 1;
      ret.type[1] = y.type[1];
      ret.in = max(ret.in, y.cnt[0]);
      ret.cnt[0] = x.cnt[0];
      ret.cnt[1] = y.cnt[1];
    }
    return ret;
  }
  if (x.type[0] == 2 && x.type[1] == 0 && y.type[0] == 2 && y.type[1] == 0) {
    ret.type[0] = 2;
    ret.type[1] = 2;
    ret.cnt[0] = x.cnt[0];
    ret.cnt[1] = y.cnt[0];
    return ret;
  }
  if (x.type[0] == 2 && x.type[1] == 0 && y.type[0] == 1) {
    ret.type[0] = 2;
    ret.type[1] = y.type[1];
    ret.cnt[0] = x.cnt[0] + y.cnt[0];
    ret.cnt[1] = y.cnt[1];
    return ret;
  }
  if (y.type[0] == 0 && x.type[1] == 1) {
    ret.type[0] = x.type[0];
    ret.type[1] = 1;
    ret.cnt[0] = x.cnt[0];
    ret.cnt[1] = x.cnt[1] + y.cnt[1];
    return ret;
  }
  ret.type[0] = x.type[0];
  ret.type[1] = y.type[1];
  ret.cnt[0] = x.cnt[0];
  ret.cnt[1] = y.cnt[1];
  if (x.type[1] == 2 && y.type[0] == 2) {
    ret.in = max(ret.in, x.cnt[1]);
    ret.in = max(ret.in, y.cnt[0]);
  } else ret.in = max(ret.in, x.cnt[1] + y.cnt[0]);
  return ret;
}

void build(int node, int left, int right) {
  if (left == right) {
    if (s[left-1] == '>') {
      tree[node][0] = Item(0);
      tree[node][1] = Item(1);
    } else {
      tree[node][0] = Item(1);
      tree[node][1] = Item(0);
    }
    return;
  }
  int mid = getmid;
  build (leftnode, left, mid);
  build (rightnode, mid+1, right);
  tree[node][0] = merge(tree[leftnode][0], tree[rightnode][0]);
  tree[node][1] = merge(tree[leftnode][1], tree[rightnode][1]);
}

void push_down(int node, int left, int right) {
  if (left == right || info[node] == 0) return;
  idx[leftnode] ^= 1;
  idx[rightnode] ^= 1;
  info[leftnode] ^= 1;
  info[rightnode] ^= 1;
  info[node] = 0;
}

void update(int node, int left, int right, int i, int j) {
  if (right < i || j < left) return;
  if (i <= left && right <= j) {
    info[node] ^= 1;
    idx[node] ^= 1;
    return;
  }
  push_down(node, left, right);
  int mid = getmid;
  update(leftnode, left, mid, i, j);
  update(rightnode, mid+1, right, i, j);
  tree[node][idx[node]] = merge(tree[leftnode][idx[leftnode]], tree[rightnode][idx[rightnode]]);
  tree[node][idx[node]^1] = merge(tree[leftnode][idx[leftnode]^1], tree[rightnode][idx[rightnode]^1]);
}

Item query(int node, int left, int right, int i, int j) {
  if (right < i || j < left) return Item();
  if (i <= left && right <= j) {
    return tree[node][idx[node]];
  }
  push_down(node, left, right);
  int mid = getmid;
  Item a = query(leftnode, left, mid, i, j);
  Item b = query(rightnode, mid+1, right, i, j);
  return merge(a, b);
}

int main() {
  ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
  cout.precision(10); cout << fixed;
#ifdef LOCAL
  freopen("../test.txt", "r", stdin);
#endif
  int n, q; cin >> n >> q;
  cin >> s;
  build (1, 1, n);
  while (q--) {
    int a, b; cin >> a >> b;
    update(1, 1, n, a, b);
    Item tmp = query(1, 1, n, a, b);
    int ret = max(tmp.cnt[0], tmp.cnt[1]);
    ret = max(ret, tmp.in);
    cout << ret << '\n';
  }
  return 0;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <ctime>
#include <deque>
#include <iostream>
#include <list>
#include <map>
#include <memory.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>
using namespace std;
typedef long double LD;
typedef long long LL;
typedef pair<LL, LL> pll;
typedef pair<int, int> pii;
typedef vector<int> vi;
#ifdef LOCAL
#define DEBUG(x) { cerr << "# " << #x << ": " << x << endl;}
#else
#define DEBUG(x)
#endif
mt19937_64 mt(time(0));
/*---------------------------------------------------------------------------------------------------
　　　　　　　　　　　 ∧＿∧
　　　　　 ∧＿∧ 　（´<_｀ ）　 Welcome to My Coding Space!
　　　　 （ ´_ゝ`）　/　 ⌒i
　　　　／　　　＼　 　  |　|
　　　 /　　 /￣￣￣￣/　　|
　 ＿_(__ﾆつ/　    ＿/ .| .|＿＿＿＿
　 　　　＼/＿＿＿＿/　（u　⊃
---------------------------------------------------------------------------------------------------*/
#define leftnode (node<<1)
#define rightnode ((node<<1)|1)
#define getmid ((left+right)>>1)

const int MAXN = 5e5 + 10;
struct Item{
  int head = -1;
  int len = 0;
  int type[2] = {};
  int in = 0;
  int cnt[2] = {};
  Item() = default;
  Item(int h) {
    head = h;
    len = 1;
    type[1-h] = 1;
    cnt[1-h] = 1;
  }
};

string s;
Item tree[MAXN<<2][2];
int idx[MAXN<<2], info[MAXN<<2];

Item merge(const Item& x, const Item& y) {
  if (x.head == -1) return y;
  if (y.head == -1) return x;
  Item ret;
  ret.head = x.head;
  ret.len = x.len + y.len;
  if ((x.head+x.len-1)%2 == y.head) ret.len--;
  ret.in = max(x.in, y.in);
  if (x.type[0] == 0 && x.type[1] == 1) {
    if (y.type[0] == 0 && y.type[1] == 1) {
      ret.type[1] = 1;
      ret.cnt[1] = x.cnt[1] + y.cnt[1];
    } else if (y.type[1] == 0) {
      ret.type[0] = 2;
      ret.cnt[0] = x.cnt[1] + y.cnt[0];
    } else {
      ret.type[0] = 2;
      ret.type[1] = y.type[1];
      ret.cnt[0] = x.cnt[1] + y.cnt[0];
      ret.cnt[1] = y.cnt[1];
    }
    return ret;
  }
  if (x.type[0] == 1 && x.type[1] == 0) {
    if (y.type[0] == 0 || y.type[0] == 1) {
      ret.type[0] = 1;
      ret.type[1] = y.type[1];
      ret.cnt[0] = x.cnt[0] + y.cnt[0];
      ret.cnt[1] = y.cnt[1];
    } else if (y.type[1] == 0) {
      ret.type[0] = 1;
      ret.type[1] = 2;
      ret.cnt[0] = x.cnt[0];
      ret.cnt[1] = y.cnt[0];
    } else {
      ret.type[0] = 1;
      ret.type[1] = y.type[1];
      ret.in = max(ret.in, y.cnt[0]);
      ret.cnt[0] = x.cnt[0];
      ret.cnt[1] = y.cnt[1];
    }
    return ret;
  }
  if (x.type[0] == 2 && x.type[1] == 0 && y.type[0] == 2 && y.type[1] == 0) {
    ret.type[0] = 2;
    ret.type[1] = 2;
    ret.cnt[0] = x.cnt[0];
    ret.cnt[1] = y.cnt[0];
    return ret;
  }
  if (x.type[0] == 2 && x.type[1] == 0 && y.type[0] == 1) {
    ret.type[0] = 2;
    ret.type[1] = y.type[1];
    ret.cnt[0] = x.cnt[0] + y.cnt[0];
    ret.cnt[1] = y.cnt[1];
    return ret;
  }
  if (y.type[0] == 0 && x.type[1] == 1) {
    ret.type[0] = x.type[0];
    ret.type[1] = 1;
    ret.cnt[0] = x.cnt[0];
    ret.cnt[1] = x.cnt[1] + y.cnt[1];
    return ret;
  }
  ret.type[0] = x.type[0];
  ret.type[1] = y.type[1];
  ret.cnt[0] = x.cnt[0];
  ret.cnt[1] = y.cnt[1];
  if (x.type[1] == 2 && y.type[0] == 2) {
    ret.in = max(ret.in, x.cnt[1]);
    ret.in = max(ret.in, y.cnt[0]);
  } else ret.in = max(ret.in, x.cnt[1] + y.cnt[0]);
  return ret;
}

void build(int node, int left, int right) {
  if (left == right) {
    if (s[left-1] == '>') {
      tree[node][0] = Item(0);
      tree[node][1] = Item(1);
    } else {
      tree[node][0] = Item(1);
      tree[node][1] = Item(0);
    }
    return;
  }
  int mid = getmid;
  build (leftnode, left, mid);
  build (rightnode, mid+1, right);
  tree[node][0] = merge(tree[leftnode][0], tree[rightnode][0]);
  tree[node][1] = merge(tree[leftnode][1], tree[rightnode][1]);
}

void push_down(int node, int left, int right) {
  if (left == right || info[node] == 0) return;
  idx[leftnode] ^= 1;
  idx[rightnode] ^= 1;
  info[leftnode] ^= 1;
  info[rightnode] ^= 1;
  info[node] = 0;
}

void update(int node, int left, int right, int i, int j) {
  if (right < i || j < left) return;
  if (i <= left && right <= j) {
    info[node] ^= 1;
    idx[node] ^= 1;
    return;
  }
  push_down(node, left, right);
  int mid = getmid;
  update(leftnode, left, mid, i, j);
  update(rightnode, mid+1, right, i, j);
  tree[node][idx[node]] = merge(tree[leftnode][idx[leftnode]], tree[rightnode][idx[rightnode]]);
  tree[node][idx[node]^1] = merge(tree[leftnode][idx[leftnode]^1], tree[rightnode][idx[rightnode]^1]);
}

Item query(int node, int left, int right, int i, int j) {
  if (right < i || j < left) return Item();
  if (i <= left && right <= j) {
    return tree[node][idx[node]];
  }
  push_down(node, left, right);
  int mid = getmid;
  Item a = query(leftnode, left, mid, i, j);
  Item b = query(rightnode, mid+1, right, i, j);
  return merge(a, b);
}

int main() {
  ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
  cout.precision(10); cout << fixed;
#ifdef LOCAL
  freopen("../test.txt", "r", stdin);
    // freopen("../output.txt", "w", stdout);
#endif
  int n, q; cin >> n >> q;
  cin >> s;
  build (1, 1, n);
  while (q--) {
    int a, b; cin >> a >> b;
    update(1, 1, n, a, b);
    Item tmp = query(1, 1, n, a, b);
    int ret = max(tmp.cnt[0], tmp.cnt[1]);
    ret = max(ret, tmp.in);
    cout << ret << '\n';
  }

/*---------------------------------------Coding Space End------------------------------------------*/
#ifdef LOCAL
  cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s." << endl;
#endif
  return 0;
}
/* author:  txingml */
/* picture is from hamayanhamayan(CF handle) */


#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <ctime>
#include <deque>
#include <iostream>
#include <list>
#include <map>
#include <memory.h>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>
using namespace std;
typedef long double LD;
typedef long long LL;
typedef pair<LL, LL> pll;
typedef pair<int, int> pii;
typedef vector<int> vi;
#ifdef LOCAL
#define DEBUG(x) { cerr << "# " << #x << ": " << x << endl;}
#else
#define DEBUG(x)
#endif
mt19937_64 mt(time(0));
/*---------------------------------------------------------------------------------------------------
　　　　　　　　　　　 ∧＿∧
　　　　　 ∧＿∧ 　（´<_｀ ）　 Welcome to My Coding Space!
　　　　 （ ´_ゝ`）　/　 ⌒i
　　　　／　　　＼　 　  |　|
　　　 /　　 /￣￣￣￣/　　|
　 ＿_(__ﾆつ/　    ＿/ .| .|＿＿＿＿
　 　　　＼/＿＿＿＿/　（u　⊃
---------------------------------------------------------------------------------------------------*/
#define leftnode (node<<1)
#define rightnode ((node<<1)|1)
#define getmid ((left+right)>>1)

const int MAXN = 5e5 + 10;
struct Item{
  bool head;
  int len = 0;
  int8_t type[2] = {};
  int in = 0;
  int cnt[2] = {};
  Item() = default;
  Item(int h) {
    head = h;
    len = 1;
    type[1-h] = 1;
    cnt[1-h] = 1;
  }
};

string s;
Item tree[MAXN<<2][2];
int idx[MAXN<<2], info[MAXN<<2];

Item merge(const Item& x, const Item& y) {
  if (x.len == 0) return y;
  if (y.len == 0) return x;
  Item ret;
  ret.head = x.head;
  ret.len = x.len + y.len;
  if ((x.head+x.len-1)%2 == y.head) ret.len--;
  ret.in = max(x.in, y.in);

  if (x.type[0] == 0 && x.type[1] == 1) {
    if (y.type[0] == 0 && y.type[1] == 1) {
      ret.type[1] = 1;
      ret.cnt[1] = x.cnt[1] + y.cnt[1];
    } else if (y.type[1] == 0) {
      ret.type[0] = 2;
      ret.cnt[0] = x.cnt[1] + y.cnt[0];
    } else {
      ret.type[0] = 2;
      ret.type[1] = y.type[1];
      ret.cnt[0] = x.cnt[1] + y.cnt[0];
      ret.cnt[1] = y.cnt[1];
    }
    return ret;
  }
  if (x.type[0] == 1 && x.type[1] == 0) {
    if (y.type[0] == 0 || y.type[0] == 1) {
      ret.type[0] = 1;
      ret.type[1] = y.type[1];
      ret.cnt[0] = x.cnt[0] + y.cnt[0];
      ret.cnt[1] = y.cnt[1];
    } else if (y.type[1] == 0) {
      ret.type[0] = 1;
      ret.type[1] = 2;
      ret.cnt[0] = x.cnt[0];
      ret.cnt[1] = y.cnt[0];
    } else {
      ret.type[0] = 1;
      ret.type[1] = y.type[1];
      ret.in = max(ret.in, y.cnt[0]);
      ret.cnt[0] = x.cnt[0];
      ret.cnt[1] = y.cnt[1];
    }
    return ret;
  }
  if (x.type[0] == 2 && x.type[1] == 0 && y.type[0] == 2 && y.type[1] == 0) {
    ret.type[0] = 2;
    ret.type[1] = 2;
    ret.cnt[0] = x.cnt[0];
    ret.cnt[1] = y.cnt[0];
    return ret;
  }
  if (x.type[0] == 2 && x.type[1] == 0 && y.type[0] == 1) {
    ret.type[0] = 2;
    ret.type[1] = y.type[1];
    ret.cnt[0] = x.cnt[0] + y.cnt[0];
    ret.cnt[1] = y.cnt[1];
    return ret;
  }
  if (y.type[0] == 0 && x.type[1] == 1) {
    ret.type[0] = x.type[0];
    ret.type[1] = 1;
    ret.cnt[0] = x.cnt[0];
    ret.cnt[1] = x.cnt[1] + y.cnt[1];
    return ret;
  }
  if (y.type[0] == 1 && y.type[1] == 0) {
    ret.type[0] = x.type[0];
    ret.type[1] = 2;
    ret.cnt[0] = x.cnt[0];
    ret.cnt[1] = x.cnt[1] + y.cnt[0];
    return ret;
  }
  ret.type[0] = x.type[0];
  ret.type[1] = y.type[1];
  ret.cnt[0] = x.cnt[0];
  ret.cnt[1] = y.cnt[1];
  if (x.type[1] == 2 && y.type[0] == 2) {
    ret.in = max(ret.in, x.cnt[1]);
    ret.in = max(ret.in, y.cnt[0]);
  } else ret.in = max(ret.in, x.cnt[1] + y.cnt[0]);
  return ret;
}

void build(int node, int left, int right) {
  if (left == right) {
    if (s[left-1] == '>') {
      tree[node][0] = Item(0);
      tree[node][1] = Item(1);
    } else {
      tree[node][0] = Item(1);
      tree[node][1] = Item(0);
    }
    return;
  }
  int mid = getmid;
  build (leftnode, left, mid);
  build (rightnode, mid+1, right);
  tree[node][0] = merge(tree[leftnode][0], tree[rightnode][0]);
  tree[node][1] = merge(tree[leftnode][1], tree[rightnode][1]);
}

void push_down(int node, int left, int right) {
  if (left == right || info[node] == 0) return;
  idx[leftnode] ^= 1;
  idx[rightnode] ^= 1;
  info[leftnode] ^= 1;
  info[rightnode] ^= 1;
  info[node] = 0;
}

void update(int node, int left, int right, int i, int j) {
  if (right < i || j < left) return;
  if (i <= left && right <= j) {
    info[node] ^= 1;
    idx[node] ^= 1;
    return;
  }
  push_down(node, left, right);
  int mid = getmid;
  update(leftnode, left, mid, i, j);
  update(rightnode, mid+1, right, i, j);
  tree[node][idx[node]] = merge(tree[leftnode][idx[leftnode]], tree[rightnode][idx[rightnode]]);
  tree[node][idx[node]^1] = merge(tree[leftnode][idx[leftnode]^1], tree[rightnode][idx[rightnode]^1]);
}

Item query(int node, int left, int right, int i, int j) {
  if (right < i || j < left) return Item();
  if (i <= left && right <= j) {
    return tree[node][idx[node]];
  }
  push_down(node, left, right);
  int mid = getmid;
  Item a = query(leftnode, left, mid, i, j);
  Item b = query(rightnode, mid+1, right, i, j);
  return merge(a, b);
}

int main() {
  ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
  cout.precision(10); cout << fixed;
#ifdef LOCAL
  freopen("../test.txt", "r", stdin);
  // freopen("../output.txt", "w", stdout);
#endif
  int n, q; cin >> n >> q;
  cin >> s;
  build (1, 1, n);
  while (q--) {
    int a, b; cin >> a >> b;
    update(1, 1, n, a, b);
    Item tmp = query(1, 1, n, a, b);
    int ret = max(tmp.cnt[0], tmp.cnt[1]);
    ret = max(ret, tmp.in);
    cout << ret << '\n';
  }

/*---------------------------------------Coding Space End------------------------------------------*/
#ifdef LOCAL
  cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s." << endl;
#endif
  return 0;
}
/* author:  txingml */
/* picture is from hamayanhamayan(CF handle) */


// start of CP 3.0
#include <bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>

//____By:sirjan13____

#define int long long
#define ld long double
#define mod 1000000007
#define mod1 mod
#define mod2 100000009
#define show(a) for(int i=0;i<a.size();i++) cout<<a[i & 1]<<" ";
#define fi first
#define se second
#define vi vector<int>
#define vs vector<string>
#define vll vector<ll>
#define pb push_back
#define pi pair<int,int>
#define si set<int>
#define sll set<ll>
#define pll pair<ll, ll>
#define sci(x) scanf("%d",&x)
#define scs(x)  scanf("%s", x)
#define scll(x) scanf("%I64d",&x)
#define all(v) v.begin(),v.end()
#define sot(v) sort(v.begin(), v.end())
#define maxheap priority_queue<int>
#define minheap priority_queue<int,vector<int>,greater<int>>
#define mp make_pair
#define fast_io() cin.sync_with_stdio(false);cout.sync_with_stdio(false);
#define PI 3.1415926535
#define long_zero 0ll
#define long_one 1ll

inline int sbt(int x){return __builtin_popcount(x);}

using namespace std;
// using namespace __gnu_pbds;

#define TRACE
#ifdef TRACE
#define deb(...) __f(#__VA_ARGS__, __VA_ARGS__)
    template <typename Arg1>
    void __f(const char* name, Arg1&& arg1){
        cout << name << " : " << arg1 << std::endl;
    }
    template <typename Arg1, typename... Args>
    void __f(const char* names, Arg1&& arg1, Args&&... args){
        const char* comma = strchr(names + 1, ','); cout.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
    }
#else
#define deb(...)
#endif
#define N 500013
bool ok;

// typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ost;

inline int mul(int a, int b, int m = mod) { return (a * b) % m; }
inline int add(int a, int b, int m = mod) { return (a + b) % m; }
inline int sub(int a, int b, int m = mod) { return (a - b + m) % m; }

int dx[][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};

int fastpow(int a, int b) {
    int res = 1;
    while(b > 0) {
        if(b & 1) res = res * a;
        a = a * a;
        b >>= 1;
    }
    return res;
}

int modinv(int a) {
    return fastpow(a, mod - 2);
}

int n, k, a[N];
string s;

// Segment Tree Template © :P

#define MAXN N

struct st {
    int p0;
    int p1;
    int s0;
    int s1;
    int p01;
    int s01;
    int p10;
    int s10;
    int max01;
    int max10;
    int len;

    st() {
        p0 = p1 = s0 = max01 = max10 = s1 = p10 = p01 = s01 = s10 = len = 1;
    }
    st(int i) {
        p0 = p1 = s0 = max01 = max10 = s1 = p10 = p01 = s01 = s10 = len = i;
    }
};

st tree[MAXN << 2];
bool lazy[MAXN << 2];

// Problem Specific
inline st merge(st lval, st rval) {
    st node(0);

    node.len = lval.len + rval.len;

    node.p0 = lval.p0;
    if(lval.p0 == lval.len) node.p0 += rval.p0;

    node.p1 = lval.p1;
    if(lval.p1 == lval.len) node.p1 += rval.p1;

    node.s0 = rval.s0;
    if(rval.s0 == rval.len) node.s0 += lval.s0;

    node.s1 = rval.s1;
    if(rval.s1 == rval.len) node.s1 += lval.s1;

    node.p01 = lval.p01;
    if(lval.p01 == lval.len) node.p01 += rval.p1;
    else if(lval.p0 == lval.len) node.p01 += rval.p01;

    node.p10 = lval.p10;
    if(lval.p10 == lval.len) node.p10 += rval.p0;
    else if(lval.p1 == lval.len) node.p10 += rval.p10;

    node.s01 = rval.s01;
    if(rval.s01 == rval.len) node.s01 += lval.s0;
    else if(rval.s1 == rval.len) node.s01 += lval.s01;

    node.s10 = rval.s10;
    if(rval.s10 == rval.len) node.s10 += lval.s1;
    else if(rval.s0 == rval.len) node.s10 += lval.s10;

    node.max01 = max(lval.max01, rval.max01);
    node.max01 = max(node.max01, max(lval.s0 + rval.p01, lval.s01 + rval.p1));
    node.max10 = max(lval.max10, rval.max10);
    node.max10 = max(node.max10, max(lval.s1 + rval.p10, lval.s10 + rval.p0));
    return node;
}

// Problem Specific
inline st get_val(int i) {
    st node;
    if(s[i - 1] == '<') {
        node.p0 = 0;
        node.s0 = 0;
    }
    else {
        node.s1 = 0;
        node.p1 = 0;
    }
    return node;
}

inline void build(int l, int r, int node = 1){
    if(l == r){
        // Problem Specific Node INIT
        tree[node] = get_val(l);
        return;
    }
    int mid = (l + r) >> 1, lc = 2 * node, rc = lc + 1;
    build(l , mid, lc);
    build(mid + 1, r, rc);
    tree[node] = merge(tree[lc], tree[rc]);
}

void f(st &node) {
    swap(node.p0,node.p1);
    swap(node.s0, node.s1);
    swap(node.p01, node.p10);
    swap(node.s01, node.s10);
    swap(node.max10, node.max01);
}

inline void push_down(int l, int r, int node){
    if(lazy[node] == 0) return;
    f(tree[node]);
    if(l != r) {
        lazy[2 * node] ^= lazy[node];
        lazy[(2 * node) + 1] ^= lazy[node];
    }
    lazy[node] = 0;
}

inline void update(int l, int r, int qs, int qe, int val, int node = 1){
    push_down(l, r, node);
    if(l > qe or r < qs) return;
    if(l >= qs and r <= qe){
        lazy[node] = val;
        push_down(l, r, node);
        return;
    }
    int mid = (l + r) >> 1, lc = 2 * node, rc = lc + 1;
    update(l , mid , qs , qe , val, lc);
    update(mid + 1 , r , qs , qe, val, rc);
    tree[node] = merge(tree[lc], tree[rc]);
}

inline st query(int l, int r, int qs, int qe, int node = 1){
    push_down(l, r, node);
    if(l > qe or r < qs) return st(0);
    if(l >= qs and r <= qe) return tree[node];
    int mid = l + r >> 1, lc = 2 * node , rc = lc + 1;
    return merge(query(l, mid, qs, qe, lc), query(mid + 1, r, qs, qe, rc));
}

// Problem

int32_t main() {
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    #endif
    fast_io()
    int q;
    cin >> n >> q;
    cin >> s;
    build(1, n);
    while(q--) {
        int l, r;
        cin >> l >> r;
        update(1, n, l, r, 1);
        st res = query(1, n, l, r);
        cout << max({res.max01, res.p1, res.s0}) << endl;
        // cout << query(1, n, l, r).max01 << endl;
    }

    return 0;
}


// start of CP 3.0
#include <bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>

//____By:sirjan13____

#define int long long
#define ld long double
#define mod 1000000007
#define mod1 mod
#define mod2 100000009
#define show(a) for(int i=0;i<a.size();i++) cout<<a[i & 1]<<" ";
#define fi first
#define se second
#define vi vector<int>
#define vs vector<string>
#define vll vector<ll>
#define pb push_back
#define pi pair<int,int>
#define si set<int>
#define sll set<ll>
#define pll pair<ll, ll>
#define sci(x) scanf("%d",&x)
#define scs(x)  scanf("%s", x)
#define scll(x) scanf("%I64d",&x)
#define all(v) v.begin(),v.end()
#define sot(v) sort(v.begin(), v.end())
#define maxheap priority_queue<int>
#define minheap priority_queue<int,vector<int>,greater<int>>
#define mp make_pair
#define fast_io() cin.sync_with_stdio(false);cout.sync_with_stdio(false);
#define PI 3.1415926535
#define long_zero 0ll
#define long_one 1ll

inline int sbt(int x){return __builtin_popcount(x);}

using namespace std;
// using namespace __gnu_pbds;

#define TRACE
#ifdef TRACE
#define deb(...) __f(#__VA_ARGS__, __VA_ARGS__)
    template <typename Arg1>
    void __f(const char* name, Arg1&& arg1){
        cout << name << " : " << arg1 << std::endl;
    }
    template <typename Arg1, typename... Args>
    void __f(const char* names, Arg1&& arg1, Args&&... args){
        const char* comma = strchr(names + 1, ','); cout.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
    }
#else
#define deb(...)
#endif
#define N 500013
bool ok;

// typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ost;

inline int mul(int a, int b, int m = mod) { return (a * b) % m; }
inline int add(int a, int b, int m = mod) { return (a + b) % m; }
inline int sub(int a, int b, int m = mod) { return (a - b + m) % m; }

int dx[][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};

int fastpow(int a, int b) {
    int res = 1;
    while(b > 0) {
        if(b & 1) res = res * a;
        a = a * a;
        b >>= 1;
    }
    return res;
}

int modinv(int a) {
    return fastpow(a, mod - 2);
}

int n, k, a[N];
string s;

// Segment Tree Template © :P

#define MAXN N

struct st {
    int p0;
    int p1;
    int s0;
    int s1;
    int p01;
    int s01;
    int p10;
    int s10;
    int max01;
    int max10;
    int len;

    st() {
        p0 = p1 = s0 = max01 = max10 = s1 = p10 = p01 = s01 = s10 = len = 1;
    }
    st(int i) {
        p0 = p1 = s0 = max01 = max10 = s1 = p10 = p01 = s01 = s10 = len = i;
    }
};

st tree[MAXN << 2];
bool lazy[MAXN << 2];

// Problem Specific
inline st merge(st lval, st rval) {
    st node(0);

    node.len = lval.len + rval.len;

    // res.zero_ones=max({x.zero_ones,y.zero_ones,x.suf_zeros+y.pre_zero_ones,x.suf_zero_ones+y.pre_ones});
    // res.one_zeros=max({x.one_zeros,y.one_zeros,x.suf_ones+y.pre_one_zeros,x.suf_one_zeros+y.pre_zeros});
    node.p0 = lval.p0;
    if(lval.p0 == lval.len) node.p0 += rval.p0;

    node.p1 = lval.p1;
    if(lval.p1 == lval.len) node.p1 += rval.p1;

    node.s0 = rval.s0;
    if(rval.s0 == rval.len) node.s0 += lval.s0;

    node.s1 = rval.s1;
    if(rval.s1 == rval.len) node.s1 += lval.s1;

    node.p01 = lval.p01;
    if(lval.p01 == lval.len) node.p01 += rval.p1;
    else if(lval.p0 == lval.len) node.p01 += rval.p01;

    node.p10 = lval.p10;
    if(lval.p10 == lval.len) node.p10 += rval.p0;
    else if(lval.p1 == lval.len) node.p10 += rval.p10;

    node.s01 = rval.s01;
    if(rval.s01 == rval.len) node.s01 += lval.s0;
    else if(rval.s1 == rval.len) node.s01 += lval.s01;

    node.s10 = rval.s10;
    if(rval.s10 == rval.len) node.s10 += lval.s1;
    else if(rval.s0 == rval.len) node.s10 += lval.s10;

    node.max01 = max(lval.max01, rval.max01);
    node.max01 = max(node.max01, max(lval.s0 + rval.p01, lval.s01 + rval.p1));
    node.max10 = max(lval.max10, rval.max10);
    node.max10 = max(node.max10, max({lval.s1 + rval.p10, lval.s10 + rval.p0, lval.p1 + rval.s0}));
    return node;
}

// Problem Specific
inline st get_val(int i) {
    st node;
    if(s[i - 1] == '<') {
        node.p0 = 0;
        node.s0 = 0;
    }
    else {
        node.s1 = 0;
        node.p1 = 0;
    }
    return node;
}

inline void build(int l, int r, int node = 1){
    if(l == r){
        // Problem Specific Node INIT
        tree[node] = get_val(l);
        return;
    }
    int mid = (l + r) >> 1, lc = 2 * node, rc = lc + 1;
    build(l , mid, lc);
    build(mid + 1, r, rc);
    tree[node] = merge(tree[lc], tree[rc]);
}

void f(st &node) {
    swap(node.p0,node.p1);
    swap(node.s0, node.s1);
    swap(node.p01, node.p10);
    swap(node.s01, node.s10);
    swap(node.max10, node.max01);
}

inline void push_down(int l, int r, int node){
    if(lazy[node] == 0) return;
    f(tree[node]);
    if(l != r) {
        lazy[2 * node] ^= lazy[node];
        lazy[(2 * node) + 1] ^= lazy[node];
    }
    lazy[node] = 0;
}

inline void update(int l, int r, int qs, int qe, int val, int node = 1){
    push_down(l, r, node);
    if(l > qe or r < qs) return;
    if(l >= qs and r <= qe){
        lazy[node] = val;
        push_down(l, r, node);
        return;
    }
    int mid = (l + r) >> 1, lc = 2 * node, rc = lc + 1;
    update(l , mid , qs , qe , val, lc);
    update(mid + 1 , r , qs , qe, val, rc);
    tree[node] = merge(tree[lc], tree[rc]);
}

inline st query(int l, int r, int qs, int qe, int node = 1){
    if(l > qe or r < qs) return st(0);
    push_down(l, r, node);
    if(l >= qs and r <= qe) return tree[node];
    int mid = l + r >> 1, lc = 2 * node , rc = lc + 1;
    return merge(query(l, mid, qs, qe, lc), query(mid + 1, r, qs, qe, rc));
}

// Problem

int32_t main() {
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    #endif
    fast_io()
    int q;
    cin >> n >> q;
    cin >> s;
    build(1, n);
    while(q--) {
        int l, r;
        cin >> l >> r;
        update(1, n, l, r, 1);
        st res = query(1, n, l, r);
        cout << max({res.max01, res.p1, res.s0}) << endl;
        // cout << query(1, n, l, r).max01 << endl;
    }

    return 0;
}


// start of CP 3.0
#include <bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>

//____By:sirjan13____

#define int long long
#define ld long double
#define mod 1000000007
#define mod1 mod
#define mod2 100000009
#define show(a) for(int i=0;i<a.size();i++) cout<<a[i & 1]<<" ";
#define fi first
#define se second
#define vi vector<int>
#define vs vector<string>
#define vll vector<ll>
#define pb push_back
#define pi pair<int,int>
#define si set<int>
#define sll set<ll>
#define pll pair<ll, ll>
#define sci(x) scanf("%d",&x)
#define scs(x)  scanf("%s", x)
#define scll(x) scanf("%I64d",&x)
#define all(v) v.begin(),v.end()
#define sot(v) sort(v.begin(), v.end())
#define maxheap priority_queue<int>
#define minheap priority_queue<int,vector<int>,greater<int>>
#define mp make_pair
#define fast_io() cin.sync_with_stdio(false);cout.sync_with_stdio(false);
#define PI 3.1415926535
#define long_zero 0ll
#define long_one 1ll

inline int sbt(int x){return __builtin_popcount(x);}

using namespace std;
// using namespace __gnu_pbds;

#define TRACE
#ifdef TRACE
#define deb(...) __f(#__VA_ARGS__, __VA_ARGS__)
    template <typename Arg1>
    void __f(const char* name, Arg1&& arg1){
        cout << name << " : " << arg1 << std::endl;
    }
    template <typename Arg1, typename... Args>
    void __f(const char* names, Arg1&& arg1, Args&&... args){
        const char* comma = strchr(names + 1, ','); cout.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
    }
#else
#define deb(...)
#endif
#define N 500013
bool ok;

// typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ost;

inline int mul(int a, int b, int m = mod) { return (a * b) % m; }
inline int add(int a, int b, int m = mod) { return (a + b) % m; }
inline int sub(int a, int b, int m = mod) { return (a - b + m) % m; }

int dx[][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};

int fastpow(int a, int b) {
    int res = 1;
    while(b > 0) {
        if(b & 1) res = res * a;
        a = a * a;
        b >>= 1;
    }
    return res;
}

int modinv(int a) {
    return fastpow(a, mod - 2);
}

int n, k, a[N];
string s;

// Segment Tree Template © :P

#define MAXN N

struct st {
    int p0;
    int p1;
    int s0;
    int s1;
    int p01;
    int s01;
    int p10;
    int s10;
    int max01;
    int max10;
    int len;

    st() {
        p0 = p1 = s0 = max01 = max10 = s1 = p10 = p01 = s01 = s10 = len = 1;
    }
    st(int i) {
        p0 = p1 = s0 = max01 = max10 = s1 = p10 = p01 = s01 = s10 = len = i;
    }
};

st tree[MAXN << 2];
bool lazy[MAXN << 2];

// Problem Specific
inline st merge(st lval, st rval) {
    st node(0);

    node.len = lval.len + rval.len;

    node.p0 = lval.p0;
    if(lval.p0 == lval.len) node.p0 += rval.p0;

    node.p1 = lval.p1;
    if(lval.p1 == lval.len) node.p1 += rval.p1;

    node.s0 = rval.s0;
    if(rval.s0 == rval.len) node.s0 += lval.s0;

    node.s1 = rval.s1;
    if(rval.s1 == rval.len) node.s1 += lval.s1;

    node.p01 = lval.p01;
    if(lval.p0 == lval.len) node.p01 += rval.p01;
    if(lval.p01 == lval.len) node.p01 += rval.p1;

    node.p10 = lval.p10;
    if(lval.p1 == lval.len) node.p10 += rval.p10;
    else if(lval.p10 == lval.len) node.p10 += rval.p0;

    node.s01 = rval.s01;
    if(rval.s1 == rval.len) node.s01 += lval.s01;
    else if(rval.s01 == rval.len) node.s01 += lval.s0;

    node.s10 = rval.s10;
    if(rval.s0 == rval.len) node.s10 += lval.s10;
    else if(rval.s10 == rval.len) node.s10 += lval.s1;

    node.max01 = max(lval.max01, rval.max01);
    node.max01 = max(node.max01, max(lval.s0 + rval.p01, lval.s01 + rval.p1));
    node.max10 = max(lval.max10, rval.max10);
    node.max10 = max(node.max10, max(lval.s1 + rval.p10, lval.s10 + rval.p0));
    // deb(node.p0, node.p1, node.p01, node.p10);
    // deb(node.p01, node.p10, node.s01, node.s10);
    // deb(node.len);
    // deb(node.max01, node.max10);

    return node;
}

// Problem Specific
inline st get_val(int i) {
    st node;
    if(s[i - 1] == '<') {
        node.p0 = 0;
        node.s0 = 0;
    }
    else {
        node.s1 = 0;
        node.p1 = 0;
    }
    return node;
}

inline void build(int l, int r, int node = 1){
    if(l == r){
        // Problem Specific Node INIT
        tree[node] = get_val(l);
        return;
    }
    int mid = (l + r) >> 1, lc = 2 * node, rc = lc + 1;
    build(l , mid, lc);
    build(mid + 1, r, rc);
    tree[node] = merge(tree[lc], tree[rc]);
}

void f(st &node) {
    swap(node.p0, node.p1);
    swap(node.s0, node.s1);
    swap(node.p01, node.p10);
    swap(node.s01, node.s10);
    swap(node.max10, node.max01);
}

inline void push_down(int l, int r, int node){
    if(lazy[node] == 0) return;
    f(tree[node]);
    if(l != r) {
        lazy[2 * node] ^= lazy[node];
        lazy[(2 * node) + 1] ^= lazy[node];
    }
    lazy[node] = 0;
}

inline void update(int l, int r, int qs, int qe, int val, int node = 1){
    push_down(l, r, node);
    if(l > qe or r < qs) return;
    if(l >= qs and r <= qe){
        lazy[node] = val;
        push_down(l, r, node);
        return;
    }
    int mid = (l + r) >> 1, lc = 2 * node, rc = lc + 1;
    update(l , mid , qs , qe , val, lc);
    update(mid + 1 , r , qs , qe, val, rc);
    tree[node] = merge(tree[lc], tree[rc]);
}

inline st query(int l, int r, int qs, int qe, int node = 1){
    push_down(l, r, node);
    if(l > qe or r < qs) return st(0);
    if(l >= qs and r <= qe) return tree[node];
    int mid = l + r >> 1, lc = 2 * node , rc = lc + 1;
    return merge(query(l, mid, qs, qe, lc), query(mid + 1, r, qs, qe, rc));
}

// Problem

int32_t main() {
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    #endif
    fast_io()
    int q;
    cin >> n >> q;
    cin >> s;
    build(1, n);
    while(q--) {
        int l, r;
        cin >> l >> r;
        update(1, n, l, r, 1);
        st res = query(1, n, l, r);
        cout << max({res.max01, res.p1, res.s0}) << endl;
        // cout << query(1, n, l, r).max01 << endl;
    }

    return 0;
}


// start of CP 3.0
#include <bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>

//____By:sirjan13____

#define int long long
#define ld long double
#define mod 1000000007
#define mod1 mod
#define mod2 100000009
#define show(a) for(int i=0;i<a.size();i++) cout<<a[i & 1]<<" ";
#define fi first
#define se second
#define vi vector<int>
#define vs vector<string>
#define vll vector<ll>
#define pb push_back
#define pi pair<int,int>
#define si set<int>
#define sll set<ll>
#define pll pair<ll, ll>
#define sci(x) scanf("%d",&x)
#define scs(x)  scanf("%s", x)
#define scll(x) scanf("%I64d",&x)
#define all(v) v.begin(),v.end()
#define sot(v) sort(v.begin(), v.end())
#define maxheap priority_queue<int>
#define minheap priority_queue<int,vector<int>,greater<int>>
#define mp make_pair
#define fast_io() cin.sync_with_stdio(false);cout.sync_with_stdio(false);
#define PI 3.1415926535
#define long_zero 0ll
#define long_one 1ll

inline int sbt(int x){return __builtin_popcount(x);}

using namespace std;
// using namespace __gnu_pbds;

#define TRACE
#ifdef TRACE
#define deb(...) __f(#__VA_ARGS__, __VA_ARGS__)
    template <typename Arg1>
    void __f(const char* name, Arg1&& arg1){
        cout << name << " : " << arg1 << std::endl;
    }
    template <typename Arg1, typename... Args>
    void __f(const char* names, Arg1&& arg1, Args&&... args){
        const char* comma = strchr(names + 1, ','); cout.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
    }
#else
#define deb(...)
#endif
#define N 500013
bool ok;

// typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ost;

inline int mul(int a, int b, int m = mod) { return (a * b) % m; }
inline int add(int a, int b, int m = mod) { return (a + b) % m; }
inline int sub(int a, int b, int m = mod) { return (a - b + m) % m; }

int dx[][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};

int fastpow(int a, int b) {
    int res = 1;
    while(b > 0) {
        if(b & 1) res = res * a;
        a = a * a;
        b >>= 1;
    }
    return res;
}

int modinv(int a) {
    return fastpow(a, mod - 2);
}

int n, k, a[N];
string s;

// Segment Tree Template © :P

#define MAXN N

struct st {
    int p0;
    int p1;
    int s0;
    int s1;
    int p01;
    int s01;
    int p10;
    int s10;
    int max01;
    int max10;
    int len;

    st() {
        p0 = p1 = s0 = max01 = max10 = s1 = p10 = p01 = s01 = s10 = len = 1;
    }
    st(int i) {
        p0 = p1 = s0 = max01 = max10 = s1 = p10 = p01 = s01 = s10 = len = i;
    }
};

st tree[MAXN << 2];
bool lazy[MAXN << 2];

// Problem Specific
inline st merge(st lval, st rval) {
    st node(0);

    node.len = lval.len + rval.len;

    node.p0 = lval.p0;
    if(lval.p0 == lval.len) node.p0 += rval.p0;

    node.p1 = lval.p1;
    if(lval.p1 == lval.len) node.p1 += rval.p1;

    node.s0 = rval.s0;
    if(rval.s0 == rval.len) node.s0 += lval.s0;

    node.s1 = rval.s1;
    if(rval.s1 == rval.len) node.s1 += lval.s1;

    node.p01 = lval.p01;
    if(lval.p01 == lval.len) node.p01 += rval.p1;
    else if(lval.p0 == lval.len) node.p01 += rval.p01;

    node.p10 = lval.p10;
    if(lval.p1 == lval.len) node.p10 += rval.p10;
    else if(lval.p10 == lval.len) node.p10 += rval.p0;

    node.s01 = rval.s01;
    if(rval.s1 == rval.len) node.s01 += lval.s01;
    else if(rval.s01 == rval.len) node.s01 += lval.s0;

    node.s10 = rval.s10;
    if(rval.s0 == rval.len) node.s10 += lval.s10;
    else if(rval.s10 == rval.len) node.s10 += lval.s1;

    node.max01 = max(lval.max01, rval.max01);
    node.max01 = max(node.max01, max(lval.s0 + rval.p01, lval.s01 + rval.p1));
    node.max10 = max(lval.max10, rval.max10);
    node.max10 = max(node.max10, max(lval.s1 + rval.p10, lval.s10 + rval.p0));
    // deb(node.p0, node.p1, node.p01, node.p10);
    // deb(node.p01, node.p10, node.s01, node.s10);
    // deb(node.len);
    // deb(node.max01, node.max10);

    return node;
}

// Problem Specific
inline st get_val(int i) {
    st node;
    if(s[i - 1] == '<') {
        node.p0 = 0;
        node.s0 = 0;
    }
    else {
        node.s1 = 0;
        node.p1 = 0;
    }
    return node;
}

inline void build(int l, int r, int node = 1){
    if(l == r){
        // Problem Specific Node INIT
        tree[node] = get_val(l);
        return;
    }
    int mid = (l + r) >> 1, lc = 2 * node, rc = lc + 1;
    build(l , mid, lc);
    build(mid + 1, r, rc);
    tree[node] = merge(tree[lc], tree[rc]);
}

void f(st &node) {
    swap(node.p0, node.p1);
    swap(node.s0, node.s1);
    swap(node.p01, node.p10);
    swap(node.s01, node.s10);
    swap(node.max10, node.max01);
}

inline void push_down(int l, int r, int node){
    if(lazy[node] == 0) return;
    f(tree[node]);
    if(l != r) {
        lazy[2 * node] ^= lazy[node];
        lazy[(2 * node) + 1] ^= lazy[node];
    }
    lazy[node] = 0;
}

inline void update(int l, int r, int qs, int qe, int val, int node = 1){
    push_down(l, r, node);
    if(l > qe or r < qs) return;
    if(l >= qs and r <= qe){
        lazy[node] = val;
        push_down(l, r, node);
        return;
    }
    int mid = (l + r) >> 1, lc = 2 * node, rc = lc + 1;
    update(l , mid , qs , qe , val, lc);
    update(mid + 1 , r , qs , qe, val, rc);
    tree[node] = merge(tree[lc], tree[rc]);
}

inline st query(int l, int r, int qs, int qe, int node = 1){
    push_down(l, r, node);
    if(l > qe or r < qs) return st(0);
    if(l >= qs and r <= qe) return tree[node];
    int mid = l + r >> 1, lc = 2 * node , rc = lc + 1;
    return merge(query(l, mid, qs, qe, lc), query(mid + 1, r, qs, qe, rc));
}

// Problem

int32_t main() {
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    #endif
    fast_io()
    int q;
    cin >> n >> q;
    cin >> s;
    build(1, n);
    while(q--) {
        int l, r;
        cin >> l >> r;
        update(1, n, l, r, 1);
        st res = query(1, n, l, r);
        cout << max({res.max01, res.p1, res.s0}) << endl;
        // cout << query(1, n, l, r).max01 << endl;
    }

    return 0;
}


// start of CP 3.0
#include <bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>

//____By:sirjan13____

#define int long long
#define ld long double
#define mod 1000000007
#define mod1 mod
#define mod2 100000009
#define show(a) for(int i=0;i<a.size();i++) cout<<a[i & 1]<<" ";
#define fi first
#define se second
#define vi vector<int>
#define vs vector<string>
#define vll vector<ll>
#define pb push_back
#define pi pair<int,int>
#define si set<int>
#define sll set<ll>
#define pll pair<ll, ll>
#define sci(x) scanf("%d",&x)
#define scs(x)  scanf("%s", x)
#define scll(x) scanf("%I64d",&x)
#define all(v) v.begin(),v.end()
#define sot(v) sort(v.begin(), v.end())
#define maxheap priority_queue<int>
#define minheap priority_queue<int,vector<int>,greater<int>>
#define mp make_pair
#define fast_io() cin.sync_with_stdio(false);cout.sync_with_stdio(false);
#define PI 3.1415926535
#define long_zero 0ll
#define long_one 1ll

inline int sbt(int x){return __builtin_popcount(x);}

using namespace std;
// using namespace __gnu_pbds;

#define TRACE
#ifdef TRACE
#define deb(...) __f(#__VA_ARGS__, __VA_ARGS__)
    template <typename Arg1>
    void __f(const char* name, Arg1&& arg1){
        cout << name << " : " << arg1 << std::endl;
    }
    template <typename Arg1, typename... Args>
    void __f(const char* names, Arg1&& arg1, Args&&... args){
        const char* comma = strchr(names + 1, ','); cout.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
    }
#else
#define deb(...)
#endif
#define N 500013
bool ok;

// typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ost;

inline int mul(int a, int b, int m = mod) { return (a * b) % m; }
inline int add(int a, int b, int m = mod) { return (a + b) % m; }
inline int sub(int a, int b, int m = mod) { return (a - b + m) % m; }

int dx[][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};

int fastpow(int a, int b) {
    int res = 1;
    while(b > 0) {
        if(b & 1) res = res * a;
        a = a * a;
        b >>= 1;
    }
    return res;
}

int modinv(int a) {
    return fastpow(a, mod - 2);
}

int n, k, a[N];
string s;

// Segment Tree Template © :P

#define MAXN N

struct st {
    int p0;
    int p1;
    int s0;
    int s1;
    int p01;
    int s01;
    int p10;
    int s10;
    int max01;
    int max10;
    int len;

    st() {
        p0 = p1 = s0 = max01 = max10 = s1 = p10 = p01 = s01 = s10 = len = 1;
    }
    st(int i) {
        p0 = p1 = s0 = max01 = max10 = s1 = p10 = p01 = s01 = s10 = len = i;
    }
};

st tree[MAXN << 2];
bool lazy[MAXN << 2];

// Problem Specific
inline st merge(st lval, st rval) {
    st node(0);

    node.len = lval.len + rval.len;

    node.p0 = lval.p0;
    if(lval.p0 == lval.len) node.p0 += rval.p0;

    node.p1 = lval.p1;
    if(lval.p1 == lval.len) node.p1 += rval.p1;

    node.s0 = rval.s0;
    if(rval.s0 == rval.len) node.s0 += lval.s0;

    node.s1 = rval.s1;
    if(rval.s1 == rval.len) node.s1 += lval.s1;

    node.p01 = lval.p01;
    if(lval.p01 == lval.len) node.p01 += rval.p1;
    else if(lval.p0 == lval.len) node.p01 += rval.p01;

    node.p10 = lval.p10;
    if(lval.p10 == lval.len) node.p10 += rval.p0;
    else if(lval.p1 == lval.len) node.p10 += rval.p10;

    node.s01 = rval.s01;
    if(rval.s01 == rval.len) node.s01 += lval.s0;
    else if(rval.s1 == rval.len) node.s01 += lval.s01;

    node.s10 = rval.s10;
    if(rval.s10 == rval.len) node.s10 += lval.s1;
    else if(rval.s0 == rval.len) node.s10 += lval.s10;

    node.max01 = max(lval.max01, rval.max01);
    node.max01 = max(node.max01, max({lval.s0 + rval.p01, lval.s01 + rval.p1, lval.p0 + rval.s1}));
    node.max10 = max(lval.max10, rval.max10);
    node.max10 = max(node.max10, max({lval.s1 + rval.p10, lval.s10 + rval.p0, lval.p1 + rval.s0}));
    return node;
}

// Problem Specific
inline st get_val(int i) {
    st node;
    if(s[i - 1] == '<') {
        node.p0 = 0;
        node.s0 = 0;
    }
    else {
        node.s1 = 0;
        node.p1 = 0;
    }
    return node;
}

inline void build(int l, int r, int node = 1){
    if(l == r){
        // Problem Specific Node INIT
        tree[node] = get_val(l);
        return;
    }
    int mid = (l + r) >> 1, lc = 2 * node, rc = lc + 1;
    build(l , mid, lc);
    build(mid + 1, r, rc);
    tree[node] = merge(tree[lc], tree[rc]);
}

void f(st &node) {
    swap(node.p0,node.p1);
    swap(node.s0, node.s1);
    swap(node.p01, node.p10);
    swap(node.s01, node.s10);
    swap(node.max10, node.max01);
}

inline void push_down(int l, int r, int node){
    if(lazy[node] == 0) return;
    f(tree[node]);
    if(l != r) {
        lazy[2 * node] ^= lazy[node];
        lazy[(2 * node) + 1] ^= lazy[node];
    }
    lazy[node] = 0;
}

inline void update(int l, int r, int qs, int qe, int val, int node = 1){
    push_down(l, r, node);
    if(l > qe or r < qs) return;
    if(l >= qs and r <= qe){
        lazy[node] = val;
        push_down(l, r, node);
        return;
    }
    int mid = (l + r) >> 1, lc = 2 * node, rc = lc + 1;
    update(l , mid , qs , qe , val, lc);
    update(mid + 1 , r , qs , qe, val, rc);
    tree[node] = merge(tree[lc], tree[rc]);
}

inline st query(int l, int r, int qs, int qe, int node = 1){
    if(l > qe or r < qs) return st(0);
    push_down(l, r, node);
    if(l >= qs and r <= qe) return tree[node];
    int mid = l + r >> 1, lc = 2 * node , rc = lc + 1;
    return merge(query(l, mid, qs, qe, lc), query(mid + 1, r, qs, qe, rc));
}

// Problem

int32_t main() {
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    #endif
    fast_io()
    int q;
    cin >> n >> q;
    cin >> s;
    build(1, n);
    while(q--) {
        int l, r;
        cin >> l >> r;
        update(1, n, l, r, 1);
        st res = query(1, n, l, r);
        cout << max({res.max01, res.p1, res.s0}) << endl;
        // cout << query(1, n, l, r).max01 << endl;
    }

    return 0;
}


// start of CP 3.0
#include <bits/stdc++.h>
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>

//____By:sirjan13____

#define int long long
#define ld long double
#define mod 1000000007
#define mod1 mod
#define mod2 100000009
#define show(a) for(int i=0;i<a.size();i++) cout<<a[i & 1]<<" ";
#define fi first
#define se second
#define vi vector<int>
#define vs vector<string>
#define vll vector<ll>
#define pb push_back
#define pi pair<int,int>
#define si set<int>
#define sll set<ll>
#define pll pair<ll, ll>
#define sci(x) scanf("%d",&x)
#define scs(x)  scanf("%s", x)
#define scll(x) scanf("%I64d",&x)
#define all(v) v.begin(),v.end()
#define sot(v) sort(v.begin(), v.end())
#define maxheap priority_queue<int>
#define minheap priority_queue<int,vector<int>,greater<int>>
#define mp make_pair
#define fast_io() cin.sync_with_stdio(false);cout.sync_with_stdio(false);
#define PI 3.1415926535
#define long_zero 0ll
#define long_one 1ll

inline int sbt(int x){return __builtin_popcount(x);}

using namespace std;
// using namespace __gnu_pbds;

#define TRACE
#ifdef TRACE
#define deb(...) __f(#__VA_ARGS__, __VA_ARGS__)
    template <typename Arg1>
    void __f(const char* name, Arg1&& arg1){
        cout << name << " : " << arg1 << std::endl;
    }
    template <typename Arg1, typename... Args>
    void __f(const char* names, Arg1&& arg1, Args&&... args){
        const char* comma = strchr(names + 1, ','); cout.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
    }
#else
#define deb(...)
#endif
#define N 500013
bool ok;

// typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ost;

inline int mul(int a, int b, int m = mod) { return (a * b) % m; }
inline int add(int a, int b, int m = mod) { return (a + b) % m; }
inline int sub(int a, int b, int m = mod) { return (a - b + m) % m; }

int dx[][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};

int fastpow(int a, int b) {
    int res = 1;
    while(b > 0) {
        if(b & 1) res = res * a;
        a = a * a;
        b >>= 1;
    }
    return res;
}

int modinv(int a) {
    return fastpow(a, mod - 2);
}

int n, k, a[N];
string s;

// Segment Tree Template © :P

#define MAXN N

struct st {
    int p0;
    int p1;
    int s0;
    int s1;
    int p01;
    int s01;
    int p10;
    int s10;
    int max01;
    int max10;
    int len;

    st() {
        p0 = p1 = s0 = max01 = max10 = s1 = p10 = p01 = s01 = s10 = len = 1;
    }
    st(int i) {
        p0 = p1 = s0 = max01 = max10 = s1 = p10 = p01 = s01 = s10 = len = i;
    }
};

st tree[MAXN << 2];
bool lazy[MAXN << 2];

// Problem Specific
inline st merge(st lval, st rval) {
    st node(0);

    node.len = lval.len + rval.len;

    node.p0 = lval.p0;
    if(lval.p0 == lval.len) node.p0 += rval.p0;

    node.p1 = lval.p1;
    if(lval.p1 == lval.len) node.p1 += rval.p1;

    node.s0 = rval.s0;
    if(rval.s0 == rval.len) node.s0 += lval.s0;

    node.s1 = rval.s1;
    if(rval.s1 == rval.len) node.s1 += lval.s1;

    node.p01 = lval.p01;
    if(lval.p0 == lval.len) node.p01 += rval.p01;
    else if(lval.p01 == lval.len) node.p01 += rval.p1;

    node.p10 = lval.p10;
    if(lval.p1 == lval.len) node.p10 += rval.p10;
    else if(lval.p10 == lval.len) node.p10 += rval.p0;

    node.s01 = rval.s01;
    if(rval.s1 == rval.len) node.s01 += lval.s01;
    else if(rval.s01 == rval.len) node.s01 += lval.s0;

    node.s10 = rval.s10;
    if(rval.s0 == rval.len) node.s10 += lval.s10;
    else if(rval.s10 == rval.len) node.s10 += lval.s1;

    node.max01 = max(lval.max01, rval.max01);
    node.max01 = max(node.max01, max(lval.s0 + rval.p01, lval.s01 + rval.p1));
    node.max10 = max(lval.max10, rval.max10);
    node.max10 = max(node.max10, max(lval.s1 + rval.p10, lval.s10 + rval.p0));
    // deb(node.p0, node.p1, node.p01, node.p10);
    // deb(node.p01, node.p10, node.s01, node.s10);
    // deb(node.len);
    // deb(node.max01, node.max10);

    return node;
}

// Problem Specific
inline st get_val(int i) {
    st node;
    if(s[i - 1] == '<') {
        node.p0 = 0;
        node.s0 = 0;
    }
    else {
        node.s1 = 0;
        node.p1 = 0;
    }
    return node;
}

inline void build(int l, int r, int node = 1){
    if(l == r){
        // Problem Specific Node INIT
        tree[node] = get_val(l);
        return;
    }
    int mid = (l + r) >> 1, lc = 2 * node, rc = lc + 1;
    build(l , mid, lc);
    build(mid + 1, r, rc);
    tree[node] = merge(tree[lc], tree[rc]);
}

void f(st &node) {
    swap(node.p0, node.p1);
    swap(node.s0, node.s1);
    swap(node.p01, node.p10);
    swap(node.s01, node.s10);
    swap(node.max10, node.max01);
}

inline void push_down(int l, int r, int node){
    if(lazy[node] == 0) return;
    f(tree[node]);
    if(l != r) {
        lazy[2 * node] ^= lazy[node];
        lazy[(2 * node) + 1] ^= lazy[node];
    }
    lazy[node] = 0;
}

inline void update(int l, int r, int qs, int qe, int val, int node = 1){
    push_down(l, r, node);
    if(l > qe or r < qs) return;
    if(l >= qs and r <= qe){
        lazy[node] = val;
        push_down(l, r, node);
        return;
    }
    int mid = (l + r) >> 1, lc = 2 * node, rc = lc + 1;
    update(l , mid , qs , qe , val, lc);
    update(mid + 1 , r , qs , qe, val, rc);
    tree[node] = merge(tree[lc], tree[rc]);
}

inline st query(int l, int r, int qs, int qe, int node = 1){
    push_down(l, r, node);
    if(l > qe or r < qs) return st(0);
    if(l >= qs and r <= qe) return tree[node];
    int mid = l + r >> 1, lc = 2 * node , rc = lc + 1;
    return merge(query(l, mid, qs, qe, lc), query(mid + 1, r, qs, qe, rc));
}

// Problem

int32_t main() {
    #ifndef ONLINE_JUDGE
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    #endif
    fast_io()
    int q;
    cin >> n >> q;
    cin >> s;
    build(1, n);
    while(q--) {
        int l, r;
        cin >> l >> r;
        update(1, n, l, r, 1);
        st res = query(1, n, l, r);
        cout << max({res.max01, res.p1, res.s0}) << endl;
        // cout << query(1, n, l, r).max01 << endl;
    }

    return 0;
}