题目也是中文的就不说题意了。新开一个变量pos记录光标在第pos个节点,因为头尾同样要虚拟一个头结点和尾结点,所以光标也就是指向当前序列的第pos-1个字符。move,prev,next直接修改pos的值就行,剩下的就都是伸展树的基本操作了。insert操作就把pos伸展到根,pos+1伸展到根的下边,向pos+1的左孩子循环添加节点就行,添加完记得自底而上pushup回来。rotate就把pos伸展到根,pos+c+1伸展到根的下边,旋转pos+c+1的左子树,delete也同样把目标区间旋转到根的右孩子的左孩子,删掉即可,get就把pos伸展到根,输出根的值。
#include <iostream> #include <cstdio> #include <algorithm> #include <memory.h> #include <cmath> #include <string> #include <cstring> using namespace std; typedef long long ll; const int maxn=2000000+50000; int pre[maxn],ch[maxn][2]; int flip[maxn]; int size[maxn]; char key[maxn]; int root,n,tot; int m,p,q,r,t,tt; struct splaytree { int pos; void pushup(int r) { size[r]=1+size[ch[r][0]]+size[ch[r][1]]; } void go_f(int r) { flip[r]^=1; swap(ch[r][0],ch[r][1]); } void pushdown(int r) { if (flip[r]) { go_f(ch[r][0]); go_f(ch[r][1]); flip[r]=0; } } void rotate(int x,int kind) { int y=pre[x]; pushdown(y); pushdown(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; pushup(y); pushup(x); } void splay(int x,int tgt) { pushdown(x); while(pre[x]!=tgt) { int y=pre[x]; pushdown(pre[y]); pushdown(y); pushdown(x); if (pre[pre[x]]==tgt) { rotate(x,ch[pre[x]][0]==x); } else { int kind=ch[pre[y]][0]==y; if (ch[y][kind]==x) { rotate(x,kind^1); rotate(x,kind); } else { rotate(y,kind); rotate(x,kind); } } } pushup(x); if (tgt==0) root=x; } void select(int k,int tgt) { int rt=root; pushdown(rt); while(true) { if (k<=size[ch[rt][0]]) rt=ch[rt][0]; else if (k==size[ch[rt][0]]+1) break; else k-=(size[ch[rt][0]]+1),rt=ch[rt][1]; pushdown(rt); } splay(rt,tgt); } void newnode(int &r,int father,char k) { r=++tot; pre[r]=father; size[r]=1; flip[r]=0; key[r]=k; ch[r][0]=ch[r][1]=0; } void init() { tot=root=0; newnode(root,0,0); newnode(ch[root][1],root,0); pushup(ch[root][1]); pushup(root); pos=1; } void Flip(int c) { select(pos,0); select(pos+c+1,root); go_f(ch[ch[root][1]][0]); } void Move(int c) { pos=c; } void Insert(int c,char *s) { select(pos,0); select(pos+1,root); int rt=ch[root][1]; newnode(ch[rt][0],rt,*s); ++s; rt=ch[rt][0]; for (;*s; rt=ch[rt][1],++s) { newnode(ch[rt][1],rt,*s); } while (pre[rt]) { pushup(rt); rt=pre[rt]; } pushup(root); } void Del(int c) { select(pos,0); select(pos+c+1,root); int t=ch[ch[root][1]][0]; pre[t]=0; ch[ch[root][1]][0]=0; pushup(ch[root][1]); pushup(root); } void Get() { select(pos+1,0); printf("%c\n",key[root]); } void Prev() { pos--; } void Next() { pos++; } void print(int rt) { if (rt==0) return ; pushdown(rt); print(ch[rt][0]); if (key[rt]) printf("%c",key[rt]); print(ch[rt][1]); } void Show() { print(root); puts(""); } }spt; char cmd[100]; char s[2*1050*1050]; string ss; int main() { // freopen("in.txt","r",stdin); scanf("%d",&n); spt.init(); for (int i=1; i<=n; i++) { scanf("%s",cmd); if (cmd[0]=='I') { scanf("%d",&m); getchar(); gets(s); spt.Insert(m,s); } else if (cmd[0]=='M') { scanf("%d",&m); spt.Move(m+1); } else if (cmd[0]=='N') { spt.Next(); } else if (cmd[0]=='P') { spt.Prev(); } else if (cmd[0]=='R') { scanf("%d",&m); spt.Flip(m); } else if (cmd[0]=='G') { spt.Get(); } else if (cmd[0]=='D') { scanf("%d",&m); spt.Del(m); } else spt.Show(); } return 0; }