您的位置:首页 > 其它

[Tyvj 1729]文艺平衡树

2015-08-07 19:45 218 查看
P1729 文艺平衡树

时间: 1000ms / 空间: 131072KiB / Java类名: Main


背景

此为平衡树系列第二道:文艺平衡树


描述

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:

翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1


输入格式

第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n) m表示翻转操作次数

接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n


输出格式

输出一行n个数字,表示原始序列经过m次变换后的结果


测试样例1


输入

5 3

1 3

1 3

1 4


输出

4 3 2 1 5


备注

n,m<=100000

Splay的特殊应用,当前点的size域代表的是它在数列中的位置,当前点的下标即为此数(可以再维护一个域,只不过这个域和下标是相等的)。所以我们需要写一个查询第k大来旋转更改区间,每次查询的时候要把标记向下传递。此时再进行Splay只需要pushdown一下当前点就可以了,因为上面都木有标记了!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100010
using namespace std;
struct Tree{
	int ch[2],rev,fa,siz;
	#define c(x,y) tree[x].ch[y]
	#define rev(x) tree[x].rev
	#define fa(x) tree[x].fa
	#define siz(x) tree[x].siz
}tree[maxn];
int n,root,m;
void Pushup(int x){
	if(x)siz(x)=siz(c(x,0))+siz(c(x,1))+1;
}
void Pushdown(int x){
	if(rev(x)){
		swap(c(x,0),c(x,1));
		rev(c(x,0))^=1;rev(c(x,1))^=1;
		rev(x)=0;
	}
}
void Rotate(int p,int x){
	int mark=p==c(x,1),y=c(p,mark^1),z=fa(x);
	if(x==c(z,0))c(z,0)=p;
	if(x==c(z,1))c(z,1)=p;
	if(y)fa(y)=x;
	fa(p)=z;fa(x)=p;c(p,mark^1)=x;c(x,mark)=y;
	Pushup(x);
}
void Splay(int p,int k){
	Pushdown(p);
	while(fa(p)!=k){
		int x=fa(p),y=fa(x);
		if(y==k)Rotate(p,x);
		else if(x==c(y,0)^p==c(x,0))Rotate(p,x),Rotate(p,y);
		else Rotate(x,y),Rotate(p,x);
	}if(!k)root=p;Pushup(p);
}
int Kth(int k){
	int now=root;
	while(now){
		Pushdown(now);
		if(k>siz(c(now,0))){
			k-=siz(c(now,0))+1;
			if(!k)return now;
			now=c(now,1);
		}else now=c(now,0);
	}return 0;
}
void Rever(int l,int r){
	l=Kth(l),r=Kth(r+2);
	Splay(l,0);Splay(r,l);
	rev(c(r,0))^=1;
}
void Build(int l,int r,int f){
	if(l>r)return;
	if(l==r){
		if(f)c(f,l>f)=l;
		fa(l)=f;
		siz(l)=1;
		return;
	}
	int mid=(l+r)>>1;
	Build(l,mid-1,mid);
	Build(mid+1,r,mid);
	if(f)c(f,mid>f)=mid;fa(mid)=f;
	Pushup(mid);
}
void Print(int x){
	if(!x)return;
	Pushdown(x);
	Print(c(x,0));
	if(x!=1&&x!=n+2)printf("%d ",x-1);
	Print(c(x,1));
}
int main(){
	scanf("%d%d",&n,&m);
	int l,r;
	Build(1,n+2,0);
	root=(n+3)>>1;
	for(int i=1;i<=m;i++){
		scanf("%d%d",&l,&r);
		Rever(l,r);
	}
	Print(root);
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: