bzoj3224 普通平衡树(splay,treap模板)

23 篇文章 0 订阅
8 篇文章 0 订阅

 

3224: Tyvj 1728 普通平衡树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 19372  Solved: 8479
[Submit][Status][Discuss]

Description

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)

Input

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

Output

对于操作3,4,5,6每行输出一个数,表示对应答案

Sample Input

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

Sample Output

106465
84185
492737

HINT

 

1.n的数据范围:n<=100000

 

2.每个数的数据范围:[-2e9,2e9]

 

 

题解:平衡树基本操作不解释

 

代码(splay版):

#include<bits/stdc++.h>
using namespace std;
int size[1000000],cnt[1000000],lc[1000000],rc[1000000],fa[1000000],val[1000000],root,tot;
void clear(){
	root=tot=0;
	memset(size,0,sizeof(size));
	memset(cnt,0,sizeof(cnt));
}
void updata(int x){
	if(x){
		size[x]=cnt[x]+(lc[x]?size[lc[x]]:0)+(rc[x]?size[rc[x]]:0);
	}
}
void zig(int x){
	int y,z;
	if(!fa[x])return;
	y=fa[x];z=fa[y];
	if(z)
		if(lc[z]==y)lc[z]=x;
		 else rc[z]=x;
		fa[x]=z;fa[y]=x;fa[rc[x]]=y;lc[y]=rc[x];rc[x]=y;
		updata(y);updata(x);
}
void zag(int x){
	int y,z;
	if(!fa[x])return;
	y=fa[x];z=fa[y];
	if(z)
	 if(lc[z]==y)lc[z]=x;
	  else rc[z]=x;
	 fa[x]=z;fa[y]=x;fa[lc[x]]=y;rc[y]=lc[x];lc[x]=y;
	 updata(y);updata(x); 
}
void splay(int &root,int x){
	int y,z;
	while(fa[x]){
		y=fa[x];z=fa[y];
		if(z){
			if(lc[z]==y&&lc[y]==x)zig(y),zig(x);
			 else if(lc[z]==y&&rc[y]==x)zag(x),zig(x);
			  else if(rc[z]==y&&lc[y]==x)zig(x),zag(x);
			   else zag(y),zag(x);
		}
		 else if(lc[y]==x)zig(x);
		  else zag(x);
	}
	root=x;
}
void sp(int x){
	splay(root,x);
}
void insert(int &k,int key,int p){
	if(!k){
		size[k=++tot]=cnt[k]=1;
		lc[k]=rc[k]=0;
		val[k]=key;
		fa[k]=p;
		sp(k);
		return;
	}
	size[k]++;
	if(key==val[k]){
		cnt[k]++;
		return;
	}
	if(key<val[k])insert(lc[k],key,k);
	 else insert(rc[k],key,k);
}
void ins(int key){
	if(!root){
		size[root=++tot]=cnt[root]=1;
		lc[root]=rc[root]=0;
		val[root]=key;fa[root]=0;
		return;
	}
	insert(root,key,0);
}
int find(int k,int key){
	while(k){
		if(val[k]==key)break;
		k=key<val[k]?lc[k]:rc[k];
	}
	if(k)sp(k);
	return k;
}
int fin(int key){
	return find(root,key);
}
int getmin(int k){
	return lc[k]?getmin(lc[k]):k;
}
int getmax(int k){
	return rc[k]?getmax(rc[k]):k;
}
void del(int key){
	int ls,rs,x,lson;
	x=fin(key);ls=lc[x];rs=rc[x];
	if(!x)return;
	if(--cnt[x])return;
	if(!ls&&!rs){
		clear();
		return;
	}
	if(!ls)root=rs,fa[rs]=0;
	 else if(!rs)root=ls,fa[ls]=0;
	  else{
	  	lson=getmax(ls);
	  	swap(lson,ls);
	  	fa[lson]=0;sp(ls);
	  	rc[ls]=rs;fa[rs]=ls;updata(ls);
	  }
}
int findkth(int k){
	int t;
	t=root;
	while(t){
		if(size[lc[t]]<k&&k<=size[lc[t]]+cnt[t])break;
		if(k<=size[lc[t]])t=lc[t];
		 else k-=size[lc[t]]+cnt[t],t=rc[t];
	}
	sp(t);
	return t;
}
int findpre(int k,int key){
	int tmp;
	if(!k)return 0;
	if(key<=val[k])return findpre(lc[k],key);
	 else{
	 	tmp=findpre(rc[k],key);
	 	return tmp?tmp:k;
	 }
}
int findnxt(int k,int key){
	if(!k)return 0;
	if(key>=val[k])return findnxt(rc[k],key);
	 else{
	 	int tmp=findnxt(lc[k],key);
	 	return tmp?tmp:k;
	 }
}
int findpr(int key){
	return findpre(root,key); 
}
int findnx(int key){
	return findnxt(root,key);
}
int main(){
	int n,i,t1,x;
	scanf("%d",&n);
	for(i=1;i<=n;i++){
		scanf("%d%d",&t1,&x);
		if(t1==1)ins(x);
		if(t1==2)del(x);
		if(t1==3){
			sp(fin(x));
			printf("%d\n",size[lc[root]]+1);
		}
		if(t1==4)printf("%d\n",val[findkth(x)]);
		if(t1==5)printf("%d\n",val[findpr(x)]);
		if(t1==6)printf("%d\n",val[findnx(x)]);
	}
}

 

 

 

treap模板:

#include<bits/stdc++.h>
using namespace std;
int rt,cnt,n,ans,vis[100001],lc[100001],rc[100001],pos[100001];
void zig(int &x){
	int y=lc[x];
	lc[x]=rc[y];rc[y]=x;
	x=y;
}
void zag(int &x){
	int y=rc[x];
	rc[x]=lc[y];lc[y]=x;
	x=y;
}
void insert(int &x,int t){
	if(!x){
		vis[x=++cnt]=t;
		pos[x]=rand();
		return;
	}
	if(t<vis[x]){
		insert(lc[x],t);
		if(pos[lc[x]]<pos[x])zig(x);
	}
	 else{
	 	insert(rc[x],t);
	 	if(pos[rc[x]]<pos[x])zag(x);
	 }
}
int getpre(int t){
	int x=rt,now=-1e9;
	while(x){
		if(t>=vis[x])now=vis[x],x=rc[x];
		 else  x=lc[x];
	}
	return now;
}
int getnext(int t){
	int x=rt,now=1e9;
	while(x){
		if(t<=vis[x])now=vis[x],x=lc[x];
		 else x=rc[x];
	}
	return now;
}
int main(){
	int t,x,y;
	scanf("%d",&n);
	scanf("%d",&ans);
	insert(rt,ans);
	while(--n){
		scanf("%d",&t);
		x=getpre(t);y=getnext(t);
		ans+=min(t-x,y-t);
		insert(rt,t);
	}
	printf("%d",ans);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值