bzoj 3224: Tyvj 1728 普通平衡树 Treap

       平衡树的基本操作(←现在才会的SB)。直接裸上Treap即可,(不要问我为什么这么像黄学长的,因为我的数据结构都是按他的模板来的)

AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#define N 100005
using namespace std;

int n,trtot,rt,ans,c[N][2],sz[N],sum[N],rd[N],val[N];
int read(){
	int x=0,fu=1; char ch=getchar();
	while (ch<'0' || ch>'9'){ if (ch=='-') fu=-1; ch=getchar(); }
	while (ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
	return x*fu;
}
void rotate(int &k,int l){
	int t=c[k][l]; c[k][l]=c[t][l^1]; c[t][l^1]=k;
	sz[t]=sz[k]; sz[k]=sz[c[k][0]]+sz[c[k][1]]+sum[k]; k=t;
}
void ins(int &k,int x){
	if (!k){
		k=++trtot;	sz[k]=sum[k]=1;
		val[k]=x; rd[k]=rand(); return;
	}
	sz[k]++;
	if (x==val[k]) sum[k]++; else
	if (x<val[k]){
		ins(c[k][0],x); if (rd[c[k][0]]<rd[k]) rotate(k,0);
	} else{
		ins(c[k][1],x); if (rd[c[k][1]]<rd[k]) rotate(k,1);
	}
}
void del(int &k,int x){
	if (x==val[k]){
		if (sum[k]>1){ sz[k]--; sum[k]--; return; }
		if (!c[k][0] || !c[k][1]) k=c[k][0]+c[k][1]; else
			if (rd[c[k][0]]<rd[c[k][1]]){ rotate(k,0); del(k,x); }
			else{ rotate(k,1); del(k,x); }
	} else{
		if (x<val[k]) del(c[k][0],x); else del(c[k][1],x);
		sz[k]--;
	}
}
int getrnk(int k,int x){
	if (x==val[k]) return sz[c[k][0]]+1; else
	if (x<val[k]) return getrnk(c[k][0],x); else
		return sz[c[k][0]]+sum[k]+getrnk(c[k][1],x);
}
int find(int k,int rst){
	if (rst<=sz[c[k][0]]) return find(c[k][0],rst); else
	if (rst>sz[c[k][0]]+sum[k]) return find(c[k][1],rst-sz[c[k][0]]-sum[k]);
		else return val[k];
}
void getpre(int k,int x){
	if (!k) return;
	if (val[k]<x){ ans=k; getpre(c[k][1],x); } else getpre(c[k][0],x);
}
void getnxt(int k,int x){
	if (!k) return;
	if (val[k]>x){ ans=k; getnxt(c[k][0],x); } else getnxt(c[k][1],x);
}
int main(){
	srand(20160316); int cas=read(),k,x;
	while (cas--){
		k=read(); x=read();
		if (k==1) ins(rt,x); else if (k==2) del(rt,x); else
		if (k==3) printf("%d\n",getrnk(rt,x)); else
		if (k==4) printf("%d\n",find(rt,x)); else{
			ans=0; if (k==5) getpre(rt,x); else getnxt(rt,x);
			printf("%d\n",val[ans]);
		}
	}
	return 0;
}


by lych

2016.3.16

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值