1. 程式人生 > >[BZOJ3223]文藝平衡樹

[BZOJ3223]文藝平衡樹

light include logs tag pla treap 父親 printf 破壞

以前看著非旋treap的題解寫了一發,沒有真正理解

最近補了一下splay,於是用來練手

因為是區間翻轉,子樹大小不變,所以pushup時兒子對父親沒有影響

因此splay($x$)之前只需一路從根pushdown到$x$即可,不需要pushdown兒子

由於pushdown時交換兒子破壞了二叉搜索樹的性質,故splay($x$)應該改為splay($k$),即splay排名第幾的節點而不是splay節點編號

#include<stdio.h>
int ch[100010][2],fa[100010],siz[100010],tag[100010],root,n;
int build(int l,int r){
	int mid=(l+r)>>1,ls=0,rs=0;
	if(l<mid)ls=build(l,mid-1);
	if(mid<r)rs=build(mid+1,r);
	siz[mid]=1;
	if(ls){
		siz[mid]+=siz[ls];
		ch[mid][0]=ls;
		fa[ls]=mid;
	}
	if(rs){
		siz[mid]+=siz[rs];
		ch[mid][1]=rs;
		fa[rs]=mid;
	}
	return mid;
}
void pushup(int x){
	siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
}
void rot(int x){
	int y,z,B,f;
	y=fa[x];
	z=fa[y];
	f=(ch[y][0]==x);
	if(root==y)root=x;
	B=ch[x][f];
	if(B)fa[B]=y;
	fa[x]=z;
	fa[y]=x;
	ch[x][f]=y;
	ch[y][f^1]=B;
	if(ch[z][f^1]==y)ch[z][f^1]=x;
	if(ch[z][f]==y)ch[z][f]=x;
	pushup(y);
	pushup(x);
}
void swap(int&a,int&b){a^=b^=a^=b;}
void pushdown(int x){
	if(tag[x]){
		swap(ch[x][0],ch[x][1]);
		if(ch[x][0])tag[ch[x][0]]^=1;
		if(ch[x][1])tag[ch[x][1]]^=1;
		tag[x]=0;
	}
}
void splay(int k){
	int x,y,z;
	x=root;
	while(1){
		pushdown(x);
		if(siz[ch[x][0]]>=k)
			x=ch[x][0];
		else if(siz[ch[x][0]]+1<k){
			k-=(siz[ch[x][0]]+1);
			x=ch[x][1];
		}else
			break;
	}
	while(x!=root){
		if(fa[x]==root)
			rot(x);
		else{
			y=fa[x];
			z=fa[y];
			if((y==ch[z][0]&&x==ch[y][0])||(y==ch[z][1]&&x==ch[y][1])){
				rot(y);
				rot(x);
			}else{
				rot(x);
				rot(x);
			}
		}
	}
}
void reverse(int l,int r){
	if(l==1){
		if(r==n)
			tag[root]^=1;
		else{
			splay(r+1);
			tag[ch[root][0]]^=1;
			splay(siz[ch[root][0]]-siz[ch[ch[root][0]][1]]);
		}
		return;
	}
	if(r==n){
		splay(l-1);
		tag[ch[root][1]]^=1;
		splay(siz[ch[root][0]]+siz[ch[ch[root][1]][0]]+2);
		return;
	}
	splay(l-1);
	int t=root;
	root=ch[root][1];
	splay(r-siz[ch[t][0]]);
	tag[ch[root][0]]^=1;
	root=fa[root];
	splay(siz[ch[root][0]]+siz[ch[ch[ch[root][1]][0]][0]]+2);
}
void dfs(int x){
	pushdown(x);
	if(ch[x][0])dfs(ch[x][0]);
	printf("%d ",x);
	if(ch[x][1])dfs(ch[x][1]);
}
int main(){
	int m,l,r;
	scanf("%d%d",&n,&m);
	root=build(1,n);
	while(m--){
		scanf("%d%d",&l,&r);
		reverse(l,r);
	}
	dfs(root);
}

[BZOJ3223]文藝平衡樹