题意:给定数字的序列 操作是翻转序列中的一段数字 或者是 将其中一段数字剪切下来 然后粘贴在剪切完的数组的一个数之后
解法:splay区间翻转,区间剪切
这个旋转操作ms有点花样的
#include<cstdio>
#include<iostream>
using namespace std;
#define maxn 333333
#define rls ch[root][0]
#define rrs ch[root][1]
#define ls ch[rt][0]
#define rs ch[rt][1]
int ch[maxn][2],num[maxn],fa[maxn],rev[maxn];
int n,m,root,cnt;
void up(int rt){
num[rt]=num[ls]+num[rs]+1;
}
void down(int rt){
swap(ls,rs);
rev[ls]^=1;rev[rs]^=1;
rev[rt]=0;
}
void build(){
memset(ch,0,sizeof ch);
memset(rev,0,sizeof rev);
for(int i=1;i<=n+2;++i)
fa[i]=i+1,num[i]=i,ch[i][0]=i-1;
root=n+2;fa[n+2]=0;
cnt=0;
}
void rot(int rt){
int f=fa[rt],side=(ch[f][1]==rt),&ll=ch[rt][!side];
fa[ll]=f;ch[f][side]=ll;
fa[rt]=fa[f];ch[fa[f]][ch[fa[f]][1]==f]=rt;
fa[f]=rt,ch[rt][!side]=f;
up(f),up(rt);
}
void splay(int rt,int aim){
while(fa[rt]!=aim){
int f=fa[rt],ff=fa[f];
if(ff==aim)rot(rt);
else if((ch[f][1]==rt)==(ch[ff][1]==f))rot(f),rot(rt);
else rot(rt),rot(rt);
}if(!aim)root=rt;
}
void find(int tot,int sub){
int rt=sub;
while(1){
if(rev[rt])down(rt);
if(num[ls]==tot-1)break;
if(num[ls]>=tot)rt=ls;
else tot-=num[ls]+1,rt=rs;
}
splay(rt,fa[sub]);
}
void flip(int l,int r){
find(l,root);
find(r-l+2,rrs);
rev[ch[rrs][0]]^=1;
}
void cut(int l,int r,int pos){
find(l,root);
find(r-l+2,rrs);
int rl=ch[rrs][0];
ch[rrs][0]=0;up(rrs),up(root);
find(pos+2,root);
find(pos+1,rls);
ch[rls][1]=rl;fa[rl]=rls;
up(rls),up(root);
}
int ans[maxn];
void print(int rt){
if(rev[rt])down(rt);
if(ls)print(ls);
ans[++cnt]=rt;
if(rs)print(rs);
}
int a,b,c;
int main(){
while(~scanf("%d%d",&n,&m)){
if(n==-1&&m==-1)break;
build();
char s[111];
while(m--){
scanf("%s",s);
if(*s=='F'){
scanf("%d%d",&a,&b);
flip(a,b);
}else if(*s=='C'){
scanf("%d%d%d",&a,&b,&c);
cut(a,b,c);
}
}
print(root);
for(int i=2;i<cnt;++i)printf(i==2?"%d":" %d",ans[i]-1);
printf("\n");
}
return 0;
}