码迷,mamicode.com
首页 > 其他好文 > 详细

[BZOJ3223]文艺平衡树

时间:2017-09-09 18:05:30      阅读:152      评论:0      收藏:0      [点我收藏+]

标签:二叉搜索树   else   swa   编号   tag   highlight   turn   log   pushd   

以前看着非旋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]文艺平衡树

标签:二叉搜索树   else   swa   编号   tag   highlight   turn   log   pushd   

原文地址:http://www.cnblogs.com/jefflyy/p/7498646.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!