#include using namespace std; #define ll long long int #define MAX 100005 #define MOD 1000000007 #define INF 1e9 #define vi vector #define vl vector #define pii pair #define pll pair #define fi first #define se second #define pb push_back #define eb emplace_back #define sarkysaurabh ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0) #define error(args...) { vector _v = split(#args, ','); err(_v.begin(), args); cerr<<'\n';} vector split(const string& s, char c) { vector v; stringstream ss(s); string x; while (getline(ss, x, c)){ v.emplace_back(x);} return move(v); } void err(vector::iterator it) {} template void err(vector::iterator it, T a, Args... args) { cerr << it -> substr((*it)[0] == ' ', it -> length()) << " = " << a << ", "; err(++it, args...); } //int bit[MAX], p[MAX]; //void upd(int i, int v=1) {while(i < MAX){bit[i] += v; i += i&-i;}} //int read(int i) {int s=0; while(i > 0){s += bit[i]; i -= i&-i;} return s;} //int fs(int i) {while(i != p[i]){p[i]=p[p[i]]; i=p[i];} return i;} //ll modexp(ll a, ll b, ll c=MOD) { ll res=1;while(b){res=b&1?(res*a)%c:res; a=(a*a)%c; b>>=1;} return res; } // auto f = [](int a, int b) -> int { return a+b; }; char animal[MAX]; int a[MAX], s[MAX], d[MAX], dp[MAX]; vi ext[MAX][4]; //0 - D,M //1 - C,E int get0(int L, int R) { int cnt, i, j; cnt = 0; for(i=L;i<=R;++i) { for(j=0;j<4;j+=2) { for(auto x : ext[i][j]) cnt += x >= L; } } return cnt; } int get1(int L, int R) { int cnt, i, j; cnt = 0; for(i=L;i<=R;++i) { for(j=1;j<4;j+=2) { for(auto x : ext[i][j]) cnt += x >= L; } } return cnt; } struct segtree{ int st[MAX*50], lazy[MAX*50], n; void build(int si, int ss, int se) { if(ss==se) { lazy[si] = st[si] = 0; return; } int mid = (ss+se)>>1; build(si<<1, ss, mid); build(si<<1|1, mid+1, se); lazy[si] = st[si] = max(st[si<<1], st[si<<1|1]); } void init(int _n) { n = _n; build(1,1,n); } void push(int si, int ss, int se) { if(!lazy[si]) return; st[si] += lazy[si]; if(ss != se) { lazy[si<<1] += lazy[si]; lazy[si<<1|1] += lazy[si]; } lazy[si] = 0; } void update(int si, int ss, int se, int qs, int qe, int val) { push(si,ss,se); if(qs>se or qe>1; update(si<<1,ss, mid, qs, qe, val); update(si<<1|1,mid+1, se, qs, qe, val); st[si] = max(st[si<<1], st[si<<1|1]); } int query(int si, int ss, int se, int qs, int qe) { push(si,ss,se); if(qs>se or qe>1; return max(query(si<<1,ss,mid,qs,qe), query(si<<1|1,mid+1,se,qs,qe)); } void update(int L, int R, int val) { update(1,1,n,L,R,val); } int query(int L, int R) { return query(1,1,n,L,R); } }seg0,seg1; struct persistent_segtree { int L[MAX*50], R[MAX*50], st[MAX*50], avl, root, n; void init(int _n) { avl = 0; n = _n; root = build(1, n); } int build(int ss, int se) { int nxt = avl++; if(ss == se) { st[nxt] = 0; return nxt; } int mid = (ss+se)>>1; L[nxt] = build(ss, mid); R[nxt] = build(mid+1,se); st[nxt] = max(st[L[nxt]], st[R[nxt]]); return nxt; } int update(int cur, int where, int val, int ss, int se) { int nxt = avl++; int mid = (ss+se)>>1; if(ss == se) { st[nxt] = st[cur] + val; return nxt; } L[nxt] = L[cur]; R[nxt] = R[cur]; if(where <= mid) L[nxt] = update(L[cur], where, val, ss, mid); else R[nxt] = update(R[cur], where, val, mid+1, se); st[nxt] = max(st[L[nxt]], st[R[nxt]]); return nxt; } void update(int pos, int val) { root = update(root, pos, val, 1, n); } int query(int cur, int ss, int se, int qs, int qe) { if(qe < ss or qs > se) return 0; if(qs<=ss and se<=qe) return st[cur]; int mid = (ss+se)>>1; return max(query(L[cur], ss, mid, qs, qe), query(R[cur], mid+1, se, qs, qe)); } int query(int l, int r) { return query(root, 1, n, l, r); } } pst0, pst1; int main() { sarkysaurabh; int t; cin>>t; while(t--) { int i, j, m, n; cin>>m>>n; for(i=0;i<=m;++i) for(j=0;j<4;++j) ext[i][j].clear(); for(i=0;i>animal[i]; if(animal[i] == 'D') a[i] = 0; if(animal[i] == 'M') a[i] = 2; if(animal[i] == 'C') a[i] = 1; if(animal[i] == 'E') a[i] = 3; } for(i=0;i>s[i]; for(i=0;i>d[i]; if(s[i] > d[i]) continue; ext[d[i]][a[i]].pb(s[i]); } dp[0] = 0; seg0.init(m+1); seg1.init(m+1); for(i=1;i<=m;++i) { dp[i] = dp[i-1]; for(auto x : ext[i][0]) seg0.update(1,x,1); for(auto x : ext[i][2]) seg0.update(1,x,1); for(auto x : ext[i][1]) seg1.update(1,x,1); for(auto x : ext[i][3]) seg1.update(1,x,1); dp[i] = max(dp[i], seg0.query(1, i-1)); dp[i] = max(dp[i], seg1.query(1, i-1)); seg0.update(i,i, dp[i]); seg1.update(i,i, dp[i]); //for(j=i-1;j>=0;--j) // dp[i] = max(dp[i], dp[j] + max(get0(j,i), get1(j,i))); //error(i , dp[i]); } dp[m+1] = -1; for(i=1;i<=n;++i) { int id = lower_bound(dp, dp+m+1, i) - dp; if(dp[id]