【分析】
哦艹一道模板题因为一些zz原因挂了一早上…还荒废了宝宝的数学课…事实证明还是劳逸结合最有效…orz
题意:开始有一个1,2,3,。。。n的序列,进行m次操作,cut a b c将区间[a,b]取出得到新序列,将区间插入到新序列第c个元素之后。filp a b 将区间a,b翻转,输出最终的序列。
思路:对于cut操作我们需要先提取出区间[a,b]然后,先暂时分裂出去,然后以c为边界分裂左右两部分,然后合并左边的和区间[a,b],将最大的旋转至根,然后和右边的合并。对于filp操作,我们可以使用lazy标记,先不翻转,需要的时候再翻转。
mdzz数组还开小了几次…结果提示TLE而不是RE…哦艹
【代码】
//HDU 3487 Play with Chain
#include<iostream>
#include<cstring>
#include<cstdio>
#define inf 1e9+7
#define ll long long
#define M(a) memset(a,0,sizeof a)
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
const int mxn=500005;
char c[10];
int n,m,sz,opt,cnt,root;
int f[mxn],ch[mxn][2],key[mxn],mark[mxn],size[mxn],data[mxn];
inline int read()
{
int x=0,f=1;char tt=getchar();
while(tt<'0'||tt>'9'){if(tt=='-')f=-1;tt=getchar();}
while(tt>='0'&&tt<='9'){x=x*10+tt-'0';tt=getchar();}
return x*f;
}
inline void clear(int x)
{
f[x]=ch[x][0]=ch[x][1]=key[x]=size[x]=0;
}
inline int get(int x) //左子树or右子树
{
if(ch[f[x]][0]==x) return 0;return 1;
}
inline void update(int x)
{
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
inline void pushdown(int x)
{
if(x && mark[x])
{
mark[x]=0;
if(ch[x][0]) mark[ch[x][0]]^=1;
if(ch[x][1]) mark[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
}
}
inline void rotate(int x)
{
pushdown(x);
int fa=f[x],fafa=f[fa],which=get(x);
ch[fa][which]=ch[x][which^1],f[ch[fa][which]]=fa;
ch[x][which^1]=fa,f[fa]=x;
f[x]=fafa;
if(fafa) ch[fafa][ch[fafa][1]==fa]=x;
update(fa),update(x);
}
inline void splay(int x,int lastfa)
{
for(int fa;(fa=f[x])!=lastfa;rotate(x))
if(f[fa]!=lastfa) rotate(get(x)==get(fa)?fa:x);
if(!lastfa) root=x;
}
inline int number(int x)
{
int now=root;
while(1)
{
pushdown(now);
if(x<=size[ch[now][0]]) now=ch[now][0];
else
{
if(x==size[ch[now][0]]+1) return now;
x=x-size[ch[now][0]]-1;
now=ch[now][1];pushdown(now);
}
}
}
inline int build(int fa,int l,int r)
{
if(l>r) return 0;
int mid=l+r>>1,now=++sz;
key[now]=data[mid],f[now]=fa,mark[now]=0;
ch[now][0]=build(now,l,mid-1);
ch[now][1]=build(now,mid+1,r);
update(now);
return now;
}
inline void print(int now)
{
pushdown(now);
if(ch[now][0]) print(ch[now][0]);
if(key[now]>-inf && key[now]<inf)
{
printf("%d",key[now]);
cnt++;
if(cnt<n) printf(" ");
}
if(ch[now][1]) print(ch[now][1]);
}
//inline void debug(int now)
//{
// if(ch[now][0]) debug(ch[now][0]);
// printf("now=%d,key=%d\n",now,key[now]);
// if(ch[now][1]) debug(ch[now][1]);
//}
int main()
{
// freopen("rand.txt","r",stdin);
int i,j,k,x,y,z;
while(~scanf("%d%d",&n,&m) && n>=0 && m>=0)
{
M(f);M(key);M(mark);M(size);M(ch);
sz=cnt=0;
fo(i,1,n) data[i+1]=i;
data[1]=-inf,data[n+2]=inf;
root=build(0,1,n+2);
fo(i,1,m)
{
scanf("%s",c);
if(c[0]=='C') //切下并插入
{
x=read(),y=read(),z=read();
x++,y++,z++;
x=number(x-1),y=number(y+1);
splay(x,0),splay(y,x);
int tmp=ch[ch[root][1]][0];
ch[ch[root][1]][0]=0;
update(ch[root][1]);
int z1=number(z),z2=number(z+1);
splay(z1,0),splay(z2,z1);
// if(ch[ch[z1][1]][0]) return 0;
ch[ch[root][1]][0]=tmp;
f[tmp]=ch[root][1];
update(ch[root][1]);
}
else //翻转
{
x=read(),y=read();
x++,y++;
x=number(x-1),y=number(y+1);
splay(x,0);
splay(y,x);
mark[ch[ch[root][1]][0]]^=1;
}
}
print(root);
printf("\n");
}
return 0;
}
/*
4 1
CUT 1 2 1
8 2
CUT 3 5 4
FLIP 2 6
-1 -1
*/