BZOJ 3223 文艺平衡树
2017.11.20
2017.11.20
请维护一个有序数列,支持对区间的翻转。
暴力!23333
这题因为翻转操作很多,当然不能用暴力……
之后发现是区间翻转问题,直接上Splay就好了。
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 100010
int n,m,rt,c[2][N],fa[N],siz[N],l,r;
bool rev[N];
void pushup(int pos){siz[pos]=siz[c[0][pos]]+siz[c[1][pos]]+1;}
inline void pushdown(int pos)
{
if(rev[pos])
{
rev[c[0][pos]]^=1,rev[c[1][pos]]^=1;
swap(c[0][c[0][pos]],c[1][c[0][pos]]);
swap(c[0][c[1][pos]],c[1][c[1][pos]]);
rev[pos]=false;
}
}
int build(int l,int r)
{
if(l>r) return 0;
int mid=(l+r)>>1;
c[0][mid]=build(l,mid-1),fa[c[0][mid]]=mid;
c[1][mid]=build(mid+1,r),fa[c[1][mid]]=mid;
pushup(mid);
return mid;
}
void DFS(int pos)
{
pushdown(pos);
if(c[0][pos]) DFS(c[0][pos]);
if(pos!=1&&pos!=n+2) printf("%d ",pos-1);
if(c[1][pos]) DFS(c[1][pos]);
}
void rotate(int &tg,int tx)
{
int ty=fa[tx],tz=fa[ty],tl=(c[1][ty]==tx),tr=tl^1;
if(ty==tg) tg=tx;
else c[c[1][tz]==ty][tz]=tx;
fa[tx]=tz,fa[ty]=tx;
fa[c[tr][tx]]=ty,c[tl][ty]=c[tr][tx],c[tr][tx]=ty;
pushup(ty),pushup(tx);
}
void splay(int &tg,int tx)
{
while(tx!=tg)
{
int ty=fa[tx],tz=fa[ty];
if(ty!=tg)
{
if((c[0][ty]==tx)^(c[0][tz]==ty)) rotate(tg,tx);
else rotate(tg,ty);
}
rotate(tg,tx);
}
}
int lookfor(int pos,int tg)
{
pushdown(pos);
if(tg<=siz[c[0][pos]]) return lookfor(c[0][pos],tg);
if(tg>siz[c[0][pos]]+1) return lookfor(c[1][pos],tg-siz[c[0][pos]]-1);
return pos;
}
int main()
{
scanf("%d%d",&n,&m);
rt=build(1,n+2);
while(m--)
{
scanf("%d%d",&l,&r);
l++,r++;
splay(rt,lookfor(rt,l-1)),splay(c[1][rt],lookfor(rt,r+1));
swap(c[0][c[0][c[1][rt]]],c[1][c[0][c[1][rt]]]);
rev[c[0][c[1][rt]]]^=1;
}
DFS(rt);
return 0;
}