通过分裂、合并来提供区间的旋转、插入操作。
可以在区间[1,n]的首尾加上虚拟节点防止RE。做各种需要用到儿子的操作前都先pushdown。
旋转时,gf->f->s,如果成一条直线,则先旋转gf,再转f;反之,先转f,再转gf。
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define rep(x,y,z) for (int x=y; x<=z; x++)
#define downrep(x,y,z) for (int x=y; x>=z; x--)
#define ms(x,y,z) memset(x,y,sizeof(z))
#define LL long long
#define repedge(x,y) for (int x=hed[y]; ~x; x=edge[x].nex)
inline int read(){
int x=0; int w=0; char ch=0;
while (ch<'0' || ch>'9') w|=ch=='-',ch=getchar();
while (ch>='0' && ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return w? -x:x;
}
const int maxn=300005;
int n,m,cnt,sz[maxn],num[maxn],val[maxn],lazy[maxn],ch[maxn][3],root;
char s[15];
void newnode(int x,int v){
lazy[x]=0; val[x]=v; sz[x]=num[x]=1;
}
void pushup(int o){
sz[o]=num[o]+sz[ch[o][0]]+sz[ch[o][1]];
}
void pushdown(int o){
if (!lazy[o]) return;
swap(ch[o][0],ch[o][1]); lazy[ch[o][0]]^=1; lazy[ch[o][1]]^=1; lazy[o]=0;
}
int build(int l,int r){
if (l>r) return 0; int x=++cnt; int mid=((l+r)>>1); newnode(x,mid);
ch[x][0]=build(l,mid-1); ch[x][1]=build(mid+1,r); pushup(x); return x;
}
void rotate(int &o,int d){
pushdown(o); int k=ch[o][d^1]; pushdown(k); ch[o][d^1]=ch[k][d]; ch[k][d]=o;
pushup(o); pushup(k); o=k;
}
int cmp(int o,int &v){
pushdown(o);
if (v<=sz[ch[o][0]]) return 0;
if (v<=sz[ch[o][0]]+num[o]) return -1;
v-=sz[ch[o][0]]+num[o]; return 1;
}
void splay(int &o,int v){
int d=cmp(o,v); if (d==-1) return;
int p=ch[o][d]; int d2=cmp(p,v);
if (d2!=-1){ splay(ch[p][d2],v); if (d2==d) rotate(o,d^1); else rotate(ch[o][d],d2^1); }
rotate(o,d^1);
}
void split(int o,int v,int &left,int &right){
splay(o,v); right=ch[o][1]; ch[o][1]=0; pushup(o); left=o;
}
int merge(int left,int right){
splay(left,sz[left]); ch[left][1]=right; pushup(left); return left;
}
void flip(int l,int r){
int left,mid,right; split(root,l,left,mid); split(mid,r-l+1,mid,right);
lazy[mid]^=1; root=merge(merge(left,mid),right);
}
void cut(int l,int r,int c){
int left,mid,right; split(root,l,left,mid); split(mid,r-l+1,mid,right);
root=merge(left,right); split(root,c+1,left,right); root=merge(merge(left,mid),right);
}
int tot;
void write(int o){
if (!o) return;
pushdown(o);
write(ch[o][0]);
if ((1<=val[o])&&(val[o]<=n)) {
++tot; if (tot==n) printf("%d\n",val[o]); else printf("%d ",val[o]);
}
write(ch[o][1]);
}
void enter(){ putchar('\n'); }
int main(){
for ( ; ; ){
scanf("%d%d",&n,&m);
if ((n==-1)&&(m==-1)) break;
cnt=0; root=build(0,n+1);
rep(i,1,m) {
scanf("%s",&s);
if (s[0]=='F'){ int l,r; scanf("%d%d",&l,&r); flip(l,r); }
if (s[0]=='C'){ int a,b,c; scanf("%d%d%d",&a,&b,&c); cut(a,b,c); }
}
tot=0; write(root);
}
return 0;
}