// iostream is too mainstream
#include <cstdio>
// bitch please
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <queue>
#include <stack>
#include <algorithm>
#define dibs reserve
#define OVER9000 1234567890
#define tisic 47
#define soclose 10e-7
#define ALL_THE(CAKE,LIE) for(auto LIE =CAKE.begin(); LIE != CAKE.end(); LIE++)
#define chocolate win
#define ff first
#define ss second
#define uint unsigned int
// mylittlepony
using namespace std;

struct fin {
	vector<int> T;
	
	fin(int N) {T.resize(N+1,0);}
	
	int lastone(int x) {return x&(x^(x-1));}
	
	int get(int pos) {
		if(pos < 0) return 0;
		int ret =0;
		for(int i =pos+1; i > 0; i -=lastone(i)) ret +=T[i];
		return ret;}
	
	void put(int pos, int val) {
		for(int i =pos+1; i < T.size(); i +=lastone(i)) T[i] +=val;}
	};

int main() {
    int T,N,Q;
    cin >> T;
    for(int t =0; t < T; t++) {
    	cin >> N >> Q;
    	string s;
    	set<int> st;
    	vector<bool> stB(N,true);
    	cin >> s;
    	fin F(N);
    	for(int i =0; i < N; i++) {
    		st.insert(i);
    		if(i > 0 && s[i-1] == '>' && s[i] == '<') F.put(i-1,1);}
    	
    	for(int i =0; i < Q; i++) {
    		int typ; cin >> typ;
    		if(typ == 3) {
    			int L,R;
    			cin >> L >> R; L -=2; R--;
    			auto it =st.upper_bound(R);
    			if(it == st.begin()) {cout << "0\n"; continue;}
    			auto jt =it; jt--;
    			int ans =F.get(R)-F.get(L);
    			if(it != st.end() && *jt > L)
    				if(s[*jt] == '>' && s[*it] == '<') ans--;
    			cout << ans << "\n";
    			continue;}
    		int x; cin >> x;
    		if(typ == 2) {
    			auto it =st.find(--x);
    			if(it == st.end()) {s[x] =(s[x] == '<')?'>':'<'; continue;}
    			auto jt =it; jt++;
    			if(jt != st.end()) {
    				if(s[x] == '>' && s[*jt] == '<') F.put(x,-1);
    				if(s[x] == '<' && s[*jt] == '<') F.put(x,1);}
    			if(it != st.begin()) {
    				jt =it; jt--;
    				if(s[*jt] == '>' && s[x] == '>') F.put(*jt,1);
    				if(s[*jt] == '>' && s[x] == '<') F.put(*jt,-1);}
    			s[x] =(s[x] == '<')?'>':'<';}
    		if(typ == 1) {
    			auto it =st.find(--x);
    			if(it == st.end()) {
    				auto jt =st.upper_bound(x);
    				if(jt != st.end()) 
    					if(s[*jt] == '<' && s[x] == '>') F.put(x,1);
    				auto kt =jt;
    				if(jt != st.begin()) {
    					jt--;
    					if(s[*jt] == '>' && s[x] == '<') F.put(*jt,1);
    					if(kt != st.end() && s[*jt] == '>' && s[*kt] == '<') F.put(*jt,-1);}
    				st.insert(x);}
    			else {
    				auto jt =it; jt++;
    				if(jt != st.end()) 
    					if(s[x] == '>' && s[*jt] == '<') F.put(x,-1);
    				if(it != st.begin()) {
    					auto kt =it; kt--;
    					if(s[*kt] == '>' && s[x] == '<') F.put(*kt,-1);
    					if(jt != st.end() && s[*kt] == '>' && s[*jt] == '<') F.put(*kt,1);}
    				st.erase(it);}
    			}}
    		}
    return 0;}
        
// look at my code
// my code is amazing