文艺平衡树(Splay)
题意
给出一个序列,m次操作翻转区间[l,r],如1,5,4,2变成2,4,5,1
求最后的序列
n,m≤100000
题解
普通的splay维护的权值,如果维护序列的话就维护序列下标即可,即splay的中序遍历就是原序列。
提取一段区间[l,r]就把l-1旋到根,r+1旋到根的右儿子,那么这段区间就在r+1的左二子那部分。
提取出来后一段区间的结构都是一颗树,那么翻转区间就在树的根打上标记代表他的左右儿子需要交换。
标记下传在find中即可,因为所有操作都要经过这一步。
#include<bits/stdc++.h> using namespace std; const int maxn=100005; const int oo=100000000; int n,m,root,num,a[maxn]; struct point{ int size,fa,v,tag,s[2]; }tr[maxn]; template<class T>inline void read(T &x){ x=0;char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} } int build(int l,int r,int f){ if(l>r) return 0; int now=++num,mid=(l+r)>>1; tr[now].fa=f; tr[now].v=a[mid]; tr[now].size++; tr[now].s[0]=build(l,mid-1,now); tr[now].s[1]=build(mid+1,r,now); tr[now].size+=tr[tr[now].s[1]].size+tr[tr[now].s[0]].size; return now; } void pushdown(int x){ if(!tr[x].tag) return ; tr[tr[x].s[0]].tag^=1; tr[tr[x].s[1]].tag^=1; swap(tr[x].s[0],tr[x].s[1]); tr[x].tag=0; } int find(int x){ int now=root; while(1){ pushdown(now); if(x<=tr[tr[now].s[0]].size) {now=tr[now].s[0]; continue;} x=x-(tr[tr[now].s[0]].size+1); if(!x) return now; now=tr[now].s[1]; } } int indenti(int x){ return tr[tr[x].fa].s[1]==x;} void connect(int x,int y,int d){ tr[x].fa=y; tr[y].s[d]=x; } void update(int x){ int ls=tr[x].s[0],rs=tr[x].s[1]; tr[x].size=tr[ls].size+tr[rs].size+1; } void rotate(int x){ int f=tr[x].fa,ff=tr[f].fa; int d1=indenti(x); int d2=indenti(f); int cs=tr[x].s[d1^1]; connect(x,ff,d2); connect(f,x,d1^1); connect(cs,f,d1); update(f); update(x); } void splay(int x,int go){ if(go==root) root=x; go=tr[go].fa; while(tr[x].fa!=go){ int f=tr[x].fa; if(tr[f].fa==go) rotate(x); else if(indenti(x)==indenti(f)) {rotate(f);rotate(x);} else {rotate(x);rotate(x);} } } void cx(int x,int y){ int l=find(x-1),r=find(y+1);//找区间[x,y]的前驱和后继 splay(l,root); splay(r,tr[l].s[1]); int pos=tr[root].s[1]; pos=tr[pos].s[0];//找到[x,y]整颗子树的根 tr[pos].tag^=1; } void nice(int x){ pushdown(x); if(tr[x].s[0]) nice(tr[x].s[0]); if(tr[x].v!=oo&&tr[x].v!=-oo) printf("%d ",tr[x].v); if(tr[x].s[1]) nice(tr[x].s[1]); } int main(){ read(n);read(m); a[1]=-oo;a[n+2]=oo; for(int i=1;i<=n;i++) a[i+1]=i; root=build(1,n+2,0); for(int i=1;i<=m;i++){ int x,y;read(x);read(y); cx(x+1,y+1);//加入了-oo } nice(root); }