#include<iostream> #include<algorithm> #define DEBUG_ENABLE 1 using namespace std; #define MAXN 100005 #define KeyNode (ch[ch[root][1]][0]) struct operate{ char c; int x; }op[MAXN]; int seg[MAXN*2][2]; int f[MAXN]; struct SplayTree{ int sz[MAXN*2]; //sz[x]-x为根结点的结点数量 int ch[MAXN*2][2]; //ch[x][0]-x的左子节点;ch[x][1]-x的右子节点 int pre[MAXN*2]; //pre[x]-x的父结点 int root,top1,top2; //root-根结点;top1-未用结点队列头指针;top2-结点回收栈的栈顶指针 int ss[MAXN*2],que[MAXN*2]; /***********************************以下代码基本不变*********************************************/ /* Rotate(x,f):f=0-将x点左旋;f=1-将x点右旋 */ inline void rotate(int x,int f){ int y=pre[x]; push_down(y); push_down(x); ch[y][!f]=ch[x][f]; pre[ch[x][f]]=y; pre[x]=pre[y]; if(pre[y]) if(ch[pre[y]][0]==y) ch[pre[y]][0]=x; else ch[pre[y]][1]=x; ch[x][f]=y; pre[y]=x; push_up(y); } /* splay(x,goal):将x结点伸展为goal结点的子节点 */ inline void splay(int x,int goal){ for(push_down(x);pre[x]!=goal;){ if(pre[pre[x]]==goal){ /* x节点的父结点的父结点为goal,进行单旋转 */ if(ch[pre[x]][0]==x) rotate(x,1); else rotate(x,0); } else{ int y=pre[x]; int z=pre[y]; if(ch[z][0]==y) if(ch[y][0]==x){ /* 一字形旋转 */ rotate(y,1); rotate(x,1); } else{ /* 之字形旋转 */ rotate(x,0); rotate(x,1); } else if(ch[y][1]==x){ /* 一字形旋转 */ rotate(y,0); rotate(x,0); } else{ /* 之字形旋转 */ rotate(x,1); rotate(x,0); } } push_up(x); if(goal==0) root=x; } } /* rotateTo(k,goal):将序列中第k个数转到goal的子节点 */ inline void rotateTo(int k,int goal){ /* 第k位要利用中序遍历来查找 */ int tmp,t; for(t=root;;){ push_down(t); /* 标记下延 */ tmp=sz[ch[t][0]]; if(k==tmp+1) break; if(k<=tmp) /* 第k个节点在t的左子树,向左遍历 */ t=ch[t][0]; else{ k-=tmp+1; t=ch[t][1]; } } splay(t,goal); } /* join(s1,s2):将s1和s2两个Splay Tree合并为一个Splay Tree,s1的所有结点都小于s2的所有结点;返回合并后的根节点 */ inline int join(int s1,int s2){ if(s1&&s2){ int right_end=getEnd(s1,1); splay(right_end,pre[s1]); ch[right_end][1]=s2; pre[s2]=right_end; push_up(right_end); return right_end; } if(s1) return s1; if(s2) return s2; return 0; } /* erase(x):把x为节点的子树删除,放到内存池 */ inline void erase(int x){ int head,tail; for(que[tail++]=x;head<tail;head++){ ss[top2++]=que[head]; if(ch[que[head]][0]) que[tail++]=ch[que[head]][0]; if(ch[que[head]][1]) que[tail++]=ch[que[head]][1]; } } /* eraseNode(x): 将x结点删除,其子树进行和并 */ inline void eraseNode(int x){ int ret = join(ch[x][0],ch[x][1]); if(pre[x]){ if(ch[pre[x]][0]==x) ch[pre[x]][0]=ret; else ch[pre[x]][1]=ret; } else{ root=ret; } if(ret) pre[ret]=pre[x]; if(pre[x]) splay(pre[x],0); pre[x]=ch[x][0]=ch[x][1]=0; // erase(x); } /* getEnd(x,c): 得到x节点最边缘的节点 c=0-最左边的 c=1-最右边的 */ inline int getEnd(int x,int c){ while(ch[x][c]){ push_down(x); x=ch[x][c]; } return x; } /* getNear(x,c): 得到x节点最近的节点 c=0-前驱节点 c=1-后继节点 */ inline int getNear(int x,int c){ if(ch[x][c]){ return getEnd(ch[x][c],1-c); } while(pre[x]&&ch[pre[x]][c]==x) x=pre[x]; return pre[x]; } /* getSucc(x): 得到x节点的后继节点 */ inline int getSucc(int x) { return getNear(x,1); } /* getPrev(x): 得到x节点的前驱节点 */ inline int getPrev(int x) { return getNear(x,0); } /*****************************************END*********************************************/ /**********************************以下代码会随着题目的不同改变****************************/ /* 标记结点 */ inline void markNode(int x){ } /* push_down 把延迟标记推到孩子 */ inline void push_down(int x){ } /* push_up 把孩子的状态更新上来 */ inline void push_up(int x){ sz[x]=val[x][1]-val[x][0]+1+sz[ch[x][0]]+sz[ch[x][1]]; } /* findKthNode(int k): 在Splay Tree中找到第k个节点 */ inline int findKthNode(int k){ /* 第k位要利用中序遍历来查找 */ int ret; int tmp,t; for(t=root;;){ push_down(t); /* 标记下延 */ tmp=sz[ch[t][0]]; if(k<=tmp){ /* 第k个节点在t的左子树,向左遍历 */ t=ch[t][0]; continue; } k-=tmp; if(k<=val[t][1]-val[t][0]+1){ ret=val[t][0]+k-1; break; } else{ k-=val[t][1]-val[t][0]+1; t=ch[t][1]; } } splay(t,0); return ret; } /* To create a new node 题目不同,函数内容不同 */ inline void newNode(int &x,int m){ if(top2) x=ss[--top2]; else x=m; ch[x][0]=ch[x][1]=pre[x]=0; sz[x]=seg[m][1]-seg[m][0]+1; val[x][0]=seg[m][0]; val[x][1]=seg[m][1]; } /* To build a splay tree 题目不同,函数内容不同 */ inline void makeTree(int &x,int l,int r,int f){ if(l>r) return ; int m=(r+l)>>1; newNode(x,m); makeTree(ch[x][0],l,m-1,x); makeTree(ch[x][1],m+1,r,x); pre[x]=f; push_up(x); } /* Initial Function 题目不同,函数内容不同 */ inline void init(int n){ ch[0][0]=ch[0][1]=pre[0]=sz[0]=0; root=top1=top2=0; /* 增加第一个边界结点 */ /* Read into the Datas */ /* 增加第二个边界节点 */ makeTree(root,1,n,0); push_up(root); } /* update 更新函数 题目不同内容不同 */ inline void update(){ } /* query 查询函数 题目不同内容不同 */ inline void query(){ } /* run() */ inline void run(int n,int m){ int i; for(i=0;i<m;i++){ if(op[i].c=='R'){ printf("%d/n",findKthNode(op[i].x+1)); } else if(op[i].c=='T'){ int x=binarySearch(op[i].x,n); // cout<<"x: "<<x<<endl; eraseNode(x); // debug(); int succ_node; splay(1,0); // debug(); succ_node=getSucc(1); splay(succ_node,root); // debug(); pre[x]=succ_node; ch[succ_node][0]=x; splay(x,0); // debug(); //push_up(succ_node); } else{ int x=binarySearch(op[i].x,n); splay(x,0); printf("%d/n",sz[ch[x][0]]); } } } /* binarySearch(k): 查找第k号人 */ inline int binarySearch(int k,int n){ int low=1,high=n,mid; while(low<=high){ mid=(low+high)>>1; if(k>=seg[mid][0]&&k<=seg[mid][1]) return mid; else if(k<seg[mid][0]) high=mid-1; else low=mid+1; } return 0; } /* isSmaller(a,b): val[a]<val[b] retrun 1*/ inline int isSmaller(int a,int b){ if(val[a][0]<val[b][0]) return 1; else if(val[a][0]==val[b][0]&&val[a][1]<val[b][1]) return 1; return 0; } /* Optional Variables 题目不同,变量不同 */ int val[MAXN*2][2]; /*****************************************END*********************************************/ /****************************************Debug*********************************************/ #if (DEBUG_ENABLE == 1) void debug() {printf("%d/n",root);Treaval(root);} void Treaval(int x) { if(x) { printf("结点%2d: 左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d , val[0] = %2d, val[1] = %2d /n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x][0],val[x][1]); Treaval(ch[x][0]); Treaval(ch[x][1]); } } #endif /*****************************************END**********************************************/ }spt; int main() { int cas=1; int t; scanf("%d",&t); while(t--){ int n,m; scanf("%d%d",&n,&m); int i,j; char in[10]; int num=1; f[0]=0; for(i=0;i<m;i++){ scanf("%s%d",in,&op[i].x); op[i].c=in[0]; if(in[0]!='R'){ f[num++]=op[i].x; } } f[num++]=n+1; sort(f,f+num); for(i=j=1;i<num;i++) if(f[i]!=f[i-1]) f[j++]=f[i]; num=j; n=1; for(i=0;i<num-1;i++){ seg[n][0]=seg[n][1]=f[i]; n++; if(f[i]+1!=f[i+1]){ seg[n][0]=f[i]+1;seg[n++][1]=f[i+1]-1;} } seg[n][0]=seg[n++][1]=f[num-1]; spt.init(n-1); // for(i=1;i<n;i++) // cout<<seg[i][0]<<" "<<seg[i][1]<<endl; // spt.debug(); printf("Case %d:/n",cas++); spt.run(n-1,m); } // system("pause"); return 0; }