题目也是中文的就不说题意了。新开一个变量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;
}