转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
通过一个变量记录光标的位置即可。
MOVE:直接改变光标位置变量
INSERT:经典旋转,插入到根的右孩子的左子树
ROTATE:经典操作,区间反转,通过一个延迟标记记录,交换左右子树。同样要用到经典的旋转
GET:得到光标位置的后继,可以GET_KTH后然后GET_NEXT,也可以直接旋转,或者旋转后GET_MIN
PREV,NEXT:都只需要改变光标位置变量
在指定旋转的时候,我用的是GET_KTH,找到位置然后再Splay旋转,也有直接旋转的,代码里也加了
#include<iostream> #include<cstring> #include<queue> #include<cstdio> #include<algorithm> #define N 1024*1024*2 #define inf 1<<29 #define MOD 100000007 #define LL long long #define Key_value ch[ch[root][1]][0] #define _match(a,b) ((a)==(b)) using namespace std; int n,q; char key[N]; int size[N],pre[N],rev[N],pos; int ch[N][2],tot,root,node[N]; //debug部分copy from hh void Treaval(int x) { if(x) { Treaval(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,key = %2c \n",x,ch[x][0],ch[x][1],pre[x],size[x],key[x]); Treaval(ch[x][1]); } } void debug() {printf("%d\n",root);Treaval(root);} //以上Debug void NewNode(int &r,char k,int father){ r=++tot; ch[r][0]=ch[r][1]=0; pre[r]=father; rev[r]=0; key[r]=k; } void Push_Up(int r){ size[r]=size[ch[r][0]]+size[ch[r][1]]+1; } void Push_Down(int r){ if(rev[r]){ swap(ch[r][0],ch[r][1]); rev[ch[r][0]]^=1; rev[ch[r][1]]^=1; rev[r]=0; } } void Bulid(int &r,int L,int R,int father,char *str){ if(L>R) return ; int mid=(L+R)/2; NewNode(r,str[mid],father); Bulid(ch[r][0],L,mid-1,r,str); Bulid(ch[r][1],mid+1,R,r,str); Push_Up(r); } void Init(){ tot=root=0; ch[root][0]=ch[root][1]=pre[root]=rev[root]=size[root]=0; Bulid(root,0,4,0," "); } void Rotate(int x,int kind){ int y=pre[x]; Push_Down(y); Push_Down(x); ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y]; ch[x][kind]=y; pre[y]=x; Push_Up(y); } void Splay(int r,int goal){ Push_Down(r); while(pre[r]!=goal){ if(pre[pre[r]]==goal) Rotate(r,ch[pre[r]][0]==r); else{ int y=pre[r]; int kind=(ch[pre[y]][0]==y); if(ch[y][kind]==r){ Rotate(r,!kind); Rotate(r,kind); } else{ Rotate(y,kind); Rotate(r,kind); } } } Push_Up(r); if(goal==0) root=r; } void RotateTo(int k,int goal) { int r=root; Push_Down(r); while(size[ch[r][0]]!=k){ if(k<size[ch[r][0]]){ r=ch[r][0]; } else { k-=(size[ch[r][0]]+1); r=ch[r][1]; } Push_Down(r); } Splay(r,goal); } int Get_Kth(int r,int k){ Push_Down(r); int t=size[ch[r][0]]+1; if(t==k) return r; if(t>k) return Get_Kth(ch[r][0],k); else return Get_Kth(ch[r][1],k-t); } int Get_Min(int r){ Push_Down(r); while(ch[r][0]){ r=ch[r][0]; Push_Down(r); } return r; } int Get_Max(int r){ Push_Down(r); while(ch[r][1]){ r=ch[r][1]; Push_Down(r); } return r; } void Reversal(int k){ int x=Get_Kth(root,pos); Splay(x,0); int y=Get_Kth(root,pos+k+1); Splay(y,root); rev[Key_value]^=1; } void Cut(int a,int b,int c){ int x=Get_Kth(root,a); int y=Get_Kth(root,b+2); Splay(x,0); Splay(y,root); int tmp=Key_value; Key_value=0; Push_Up(ch[root][1]); Push_Up(root); int z=Get_Kth(root,c+1); Splay(z,0); int m=Get_Min(ch[root][1]); Splay(m,root); Key_value=tmp; pre[Key_value]=ch[root][1]; Push_Up(ch[root][1]); Push_Up(root); } int cnt; void InOrder(int r){ if(r==0) return; Push_Down(r); InOrder(ch[r][0]); if(cnt>=1&&cnt<=size[root]-5) printf("%c",key[r]); cnt++; InOrder(ch[r][1]); } void Insert(char *str){ int len=strlen(str); int x=Get_Kth(root,pos); Splay(x,0); // RotateTo(pos,0); int m=Get_Min(ch[root][1]); Splay(m,root); Bulid(Key_value,0,len-1,ch[root][1],str); } void Delete(int k){ // RotateTo(pos,0); int x=Get_Kth(root,pos); Splay(x,0); int y=Get_Kth(root,pos+k+1); Splay(y,root); pre[Key_value]=0; Key_value=0; Push_Up(ch[root][1]); Push_Up(root); } char Get_Answer(){ int x=Get_Kth(root,pos); Splay(x,0); // RotateTo(pos,0); int y=Get_Min(ch[root][1]); return key[y]; } char str[N]; int main(){ //freopen("editor1.in","r",stdin); while(scanf("%d",&q)!=EOF){ Init(); int k; pos=1;//光标初始位置 while(q--){ scanf("%s",str,&k); if(str[0]=='I'){ scanf("%d",&k); getchar(); gets(str); Insert(str); } else if(str[0]=='M'){ scanf("%d",&k); pos=k+1; } else if(str[0]=='D'){ scanf("%d",&k); Delete(k); } else if(str[0]=='R'){ scanf("%d",&k); Reversal(k); } else if(str[0]=='G') printf("%c\n",Get_Answer()); else if(str[0]=='P') pos--; else pos++; } } return 0; }