题意:开始有一个1-n的序列,进行m次操作,cut a b c将区间[a,b]取出得到新序列,将区间插入到新序列第c个元素之后。filp a b 将区间a,b翻转,输出最终的序列。
思路:现将a-b这个区间取出来,然后再来将c这个位置断开,然后合并左边的和区间[a,b],将最大的旋转至根,然后和右边的合并.
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6;
const int inf=0x3f3f3f3f;
int sz,root;
int key[N],size[N],f[N],ch[N][2],lazy[N];
int n,m;
int a[N],ans[N];
int k;
bool get(int x)
{
return ch[f[x]][1]==x;
}
void Modify(int x)
{
if(!x)return;
lazy[x]^=1;
}
void pushup(int x)
{
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
void pushdown(int x)
{
if(lazy[x]&&x)
{
lazy[ch[x][0]]^=1;
lazy[ch[x][1]]^=1;
lazy[x]=0;
swap(ch[x][0],ch[x][1]);
}
}
void rotate(int x)
{
int old=f[x],oldf=f[old],whichx=get(x);
ch[old][whichx]=ch[x][whichx^1];
f[ch[old][whichx]]=old;
ch[x][whichx^1]=old;
f[old]=x;
f[x]=oldf;
if(oldf)
ch[oldf][ch[oldf][1]==old]=x;
pushup(old);
pushup(x);
}
void splay(int x,int goal)
{
int y,z;
pushdown(x);
while(f[x]!=goal)
{
y=f[x],z=f[y];
if(z==goal)
{
pushdown(y);
pushdown(x);
rotate(x);
}
else
{
pushdown(z);
pushdown(y);
pushdown(x);
if((ch[z][0]==y) == (ch[y][0]==x)) rotate(y);
else rotate(x);
}
}
if(!goal)root=x;
}
int find(int x)
{
int now=root;
while(1)
{
pushdown(now);
if(x<=size[ch[now][0]])now=ch[now][0];
else
{
x-=size[ch[now][0]]+1;
if(!x)return now;
now=ch[now][1];
}
}
}
int pre()
{
int now=root;
pushdown(now);
while(ch[now][1])
{
now=ch[now][1];
pushdown(now);
}
return now;
}
int build(int l,int r,int x)
{
if(l>r)return 0;
int mid=(l+r)/2;
int now=++sz;
key[now]=a[mid];
f[now]=x;
lazy[now]=0;
ch[now][0]=build(l,mid-1,now);
ch[now][1]=build(mid+1,r,now);
pushup(now);
return now;
}
void init()
{
sz=root=0;
memset(key,0,sizeof(key));
memset(lazy,0,sizeof(lazy));
memset(size,0,sizeof(size));
memset(ch,0,sizeof(ch));
memset(f,0,sizeof(f));
for(int i=2;i<=n+1;i++)
a[i]=i-1;
a[1]=-inf;
a[n+2]=inf;
root=build(1,n+2,0);
}
void turn(int l,int r)
{
l=find(l);
r=find(r+2);
splay(l,0);
splay(r,root);
}
void merge(int root1,int root2)/*root2接到root1右子树,要求root1无右子树*/
{
ch[root1][1]=root2;
f[root2]=root1;
}
void work(int l,int r,int c)//将一个区间放在某个位置之后
{
turn(l,r);
int root1=ch[ch[root][1]][0];
ch[ch[root][1]][0]=0;
pushup(ch[root][1]);
pushup(root);
splay(find(c+1),0);
int root2=ch[root][1];
merge(root,root1);
pushup(root);
splay(pre(),0);
merge(root,root2);
pushup(root);
}
void write(int now)
{
pushdown(now);
if(ch[now][0])write(ch[now][0]);
if(key[now]!=-inf&&key[now]!=inf)ans[k++]=key[now];
if(ch[now][1])write(ch[now][1]);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
if(n==-1&&m==-1)break;
init();
char op[10];
int L,R,C;
while(m--)
{
scanf("%s%d%d",op,&L,&R);
if(op[0]=='F')
{
turn(L,R);
Modify(ch[ch[root][1]][0]);
}
else
{
scanf("%d",&C);
work(L,R,C);
}
}
k=1;
write(root);
for(int i=1;i<=n;i++)
{
if(i>1)printf(" ");
printf("%d",ans[i]);
}
printf("\n");
}
return 0;
}