有一个数列(1,2,3......,n),有两种操作
CUT a b c 把数列[a,b]截去,插入截去后的数列的c号元素后面
FLIP a b 把数列[a,b]翻转
splay水过
#include<cstdio>
#include<cstring>
#define MAXN 300010
int ans[MAXN],cnt,n,m,root,tot,ch[MAXN][2],sz[MAXN],fa[MAXN],v[MAXN],a[MAXN],rev[MAXN];
char ops[10];
inline void Swap(int &a,int &b)
{int c = a; a = b; b = c;}
void pushup(int x)
{
sz[x] = sz[ch[x][0]]+sz[ch[x][1]]+1;
}
void pushdown(int x)
{
if(rev[x])
{
rev[ch[x][0]] ^= 1;
rev[ch[x][1]] ^= 1;
Swap(ch[x][0],ch[x][1]);
rev[x] = 0;
}
}
void rotate(int x)
{
int y = fa[x],z = fa[y],f = (ch[y][1]==x);
ch[y][f] = ch[x][!f];
if(ch[y][f]) fa[ch[y][f]] = y;
ch[x][!f] = y,fa[y] = x;
fa[x] = z;
if(z) ch[z][ch[z][1]==y] = x;
pushup(y);
}
void splay(int x,int goal)
{
for(int y; (y=fa[x]) != goal; rotate(x))
{
int z = fa[y];
if(z != goal)
{
if((ch[z][0]==y) == (ch[y][0]==x)) rotate(y);
else rotate(x);
}
}
if(!goal) root = x;
pushup(x);
}
void New(int &x,int val)
{
x = ++tot;
v[x] = val;
sz[x] = 1;
}
void build_tree(int &x,int L,int R,int F)
{
int mid = (L+R)/2;
New(x,a[mid]);
fa[x] = F;
if(L < mid) build_tree(ch[x][0],L,mid-1,x);
if(R > mid) build_tree(ch[x][1],mid+1,R,x);
pushup(x);
}
void rotateto(int k,int goal)
{
int x = root;
while(1)
{
pushdown(x);
if(k > sz[ch[x][0]]+1) k -= sz[ch[x][0]]+1,x = ch[x][1];
else if(k < sz[ch[x][0]]+1) x = ch[x][0];
else break;
}
splay(x,goal);
}
void reverse(int L,int R)
{
rotateto(L,0);
rotateto(R+2,root);
int u = ch[ch[root][1]][0];
rev[u] ^= 1;
}
void move(int L,int R,int x)
{
rotateto(L,0);
rotateto(R+2,root);
int u = ch[ch[root][1]][0];
ch[ch[root][1]][0] = 0;
pushup(ch[root][1]);
pushup(root);
rotateto(x+1,0);//这里被坑了,给出的就是剩下数当中第x号元素,不用减去sz[u]
rotateto(x+2,root);
ch[ch[root][1]][0] = u;
fa[u] = ch[root][1];
pushup(ch[root][1]);
pushup(root);
}
void Print(int x)
{
if(x == 0) return;
pushdown(x);
Print(ch[x][0]);
if(v[x] != 0)
ans[++cnt] = v[x];
Print(ch[x][1]);
}
void init()
{
root = tot = cnt = 0;
memset(sz,0,sizeof sz);
memset(rev,0,sizeof rev);
memset(ch,0,sizeof ch);
memset(fa,0,sizeof fa);
}
int main()
{
int x,y,z;
while(scanf("%d%d",&n,&m) != EOF)
{
init();
for(int i = 1; i <= n; i++) a[i] = i;
build_tree(root,0,n+1,0);//这里多插入了0,n+1两个节点
if(n == m&&n == -1) return 0;
for(int i = 1; i <= m; i++)
{
scanf("%s",ops);
if(ops[0] == 'C')
{
scanf("%d%d%d",&x,&y,&z);
move(x,y,z);
}
else
{
scanf("%d%d",&x,&y);
reverse(x,y);
}
}
Print(root);
printf("%d",ans[1]);
for(int i = 2; i <= cnt; i++)
printf(" %d",ans[i]);
printf("\n");
}
}