小奇成功打开了大科学家的电脑。
大科学家打算前往n处景点旅游,他用一个序列来维护它们之间的顺序。初
始时,序列为1,2,...,n。
接着,大科学家进行m次操作来打乱顺序。每次操作有6步:
1、从序列开头(左端)取出A个数(此时序列剩下n-A个数)
2、从序列开头取出B个数
3、将第1步取出的A个数按原顺序放回序列开头
4、从序列开头取出C个数
5、将第2步取出的B个数逆序放回序列开头
6、将第4步取出的C个数按原顺序放回序列开头
你需要求出最终序列。
第一行两个数n,m。接下来m行,每行三个数A,B,C。
n,m<=100000
非旋转treap模板题,直接按题意操作就好了,输出时直接dfs一遍整棵treap,注意不要忘记下传旋转标记。
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<stack>
#include<cstdio>
#include<vector>
#include<bitset>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int r[100010];
int ls[100010];
int rs[100010];
int size[100010];
int v[100010];
int s[100010];
int cnt;
int n,m;
int A,B,C;
int x,y,z;
int root;
inline int build(int x)
{
int rt=++cnt;
v[rt]=x;
r[rt]=rand();
size[rt]=1;
return rt;
}
inline void pushup(int rt)
{
size[rt]=size[ls[rt]]+size[rs[rt]]+1;
}
inline void pushdown(int rt)
{
if(s[rt])
{
s[rt]^=1;
s[ls[rt]]^=1;
s[rs[rt]]^=1;
swap(ls[rt],rs[rt]);
}
}
inline void split(int rt,int &x,int &y,int k)
{
if(!rt)
{
x=y=0;
return ;
}
pushdown(rt);
if(size[ls[rt]]>=k)
{
y=rt;
split(ls[rt],x,ls[y],k);
pushup(rt);
}
else
{
x=rt;
split(rs[rt],rs[x],y,k-size[ls[rt]]-1);
pushup(rt);
}
}
inline int merge(int x,int y)
{
if(!x||!y)
{
return x+y;
}
pushdown(x);
pushdown(y);
if(r[x]<r[y])
{
rs[x]=merge(rs[x],y);
pushup(x);
return x;
}
else
{
ls[y]=merge(x,ls[y]);
pushup(y);
return y;
}
}
inline int build(int l,int r)
{
if(l==r)
{
return build(l);
}
int mid=(l+r)>>1;
return merge(build(l,mid),build(mid+1,r));
}
inline void print(int rt)
{
pushdown(rt);
if(ls[rt])
{
print(ls[rt]);
}
printf("%d ",v[rt]);
if(rs[rt])
{
print(rs[rt]);
}
}
int main()
{
srand(12378);
scanf("%d%d",&n,&m);
root=build(1,n);
while(m--)
{
scanf("%d%d%d",&A,&B,&C);
split(root,x,y,A);
split(y,y,z,B);
s[y]^=1;
x=merge(x,z);
split(x,x,z,C);
root=merge(merge(x,y),z);
}
print(root);
}