【moban】treap板子

其实感觉treap和splay一样都是玄学?orz 不过这个选随机数种子挺好van的 LOJ104普通平衡树 题就不放了,基本上操作和splay一样,只是这个是tree + heap 就是随机一个值,让值小的(大的) 放在最高头(堆顶)来进行旋转,只会在删除和添加的地方旋转,利用随机树保证其平衡,而splay是每次操作都对整棵树进行选择,通过均摊来保证平衡(玄学平衡) orz orz orz别的二叉查找树该怎么操作怎么操作。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#define zig(x) zigzag(x,1)
#define zag(x) zigzag(x,2)
using namespace std;
const int maxn = 200005;
int n,tot,rt;
int alls;
struct node
{
	int ls,rs,dat,pri,fa,cc,siz;
}Z[maxn];
void putup(int x)
{ Z[x].siz=Z[x].cc+Z[Z[x].ls].siz+Z[Z[x].rs].siz; }
void putupall(int x)
{
	putup(x); 
	if(Z[x].fa) putupall(Z[x].fa); 
}
int LJ[maxn],ljt;
int getnew()
{
	int p ;
	if(ljt) p = LJ[ljt--];
	p = ++tot;
	Z[p].ls = Z[p].rs = Z[p].pri = Z[p].dat = Z[p].fa = Z[p].cc = Z[p].siz = 0;
	return p;
}
void zigzag(int x,int knd)
{
	int y=Z[x].fa,z=Z[y].fa;
	if(z)
	{
		if(Z[z].ls==y) Z[z].ls = x;
		else Z[z].rs = x; 
	}
	Z[x].fa = z; Z[y].fa = x;
	if(knd==1)
	{
		Z[y].ls = Z[x].rs;
		Z[Z[y].ls].fa = y;
		Z[x].rs = y;
	}
	else
	{
		Z[y].rs = Z[x].ls;
		Z[Z[y].rs].fa = y;
		Z[x].ls = y;
	}
	if(!Z[x].fa) rt = x;
	putup(y); putup(x);
}
void ins(int key)
{
	++alls;
	if(!rt)
	{
		rt = getnew();
		Z[rt].dat = key; Z[rt].pri = rand();
		Z[rt].ls = Z[rt].rs = Z[rt].fa = 0;
		Z[rt].siz = Z[rt].cc = 1;
		return;
	}
	int now = rt,p;
	while(now)
	{
		if(Z[now].dat==key)
		{
			Z[now].cc++;
			Z[now].siz++;
			putupall(now);
			return;
		}
		else if(Z[now].dat<key)
		{
			if(Z[now].rs)now = Z[now].rs;
			else
			{
				p = getnew();
				Z[now].rs = p;
				break;
			}
		}
		else
		{
			if(Z[now].ls)now = Z[now].ls;
			else
			{
				p = getnew();
				Z[now].ls = p;
				break;
			}
		}
	}
	Z[p].dat = key; Z[p].siz=Z[p].cc=1; Z[p].ls = Z[p].rs = 0 ;
	Z[p].fa = now; Z[p].pri = rand();
	putupall(p);
	while(Z[p].pri<Z[Z[p].fa].pri)
	{
		if(Z[Z[p].fa].ls==p) zig(p);
		else zag(p);
	}
}
int fi(int key)
{
	int p = rt;
	while(p)
	{
		if(Z[p].dat==key) return p;
		if(Z[p].dat<key) p = Z[p].rs;
		else p = Z[p].ls;
	}
	return 0;
}
int getmin(int p)
{
	while(Z[p].ls) p = Z[p].ls;
	return p;
}
int getmax(int p)
{
	while(Z[p].rs) p = Z[p].rs;
	return p;
}
void del(int key)
{
	--alls;
	if(!alls) rt = 0; 
	int p = fi(key);
	if(!p) return;
	if(Z[p].cc>1)
	{
		--Z[p].cc; --Z[p].siz; 
		putupall(p);
		return;
	}
	while(Z[p].ls||Z[p].rs)
	{
		if(!Z[p].ls) { zag(Z[p].rs); continue; }
		if(!Z[p].rs) { zig(Z[p].ls); continue; }
		if(Z[Z[p].ls].pri<Z[Z[p].rs].pri) zig(Z[p].ls);
		else zag(Z[p].rs);
	}
	putup(p);
	if(Z[p].fa)
	{
	if(p==Z[Z[p].fa].ls) Z[Z[p].fa].ls = 0;
	else Z[Z[p].fa].rs = 0;
	putupall(Z[p].fa);
	}
	LJ[++ljt] = p; 
}
int getk(int k)
{
	int p = rt;
	while(k)
	{
		if(Z[Z[p].ls].siz>=k) p = Z[p].ls;
		else if(Z[Z[p].ls].siz+Z[p].cc<k) k-=Z[Z[p].ls].siz+Z[p].cc,p = Z[p].rs;
		else return p;
	}
	return 0;
}
int getpaiming(int key)
{
	int p = fi(key);
	if(p==rt) return Z[Z[p].ls].siz+1;
	int now = rt;
	int kk = 0;
	while(now)
	{
		if(now==p) { kk+=Z[Z[now].ls].siz; break; };
		if(Z[now].dat<key)
		{
			kk += Z[Z[now].ls].siz + Z[now].cc ; now = Z[now].rs;
		}
		else now = Z[now].ls;
	}
	return kk+1;
}
int getqianqu(int key)
{
	int p = rt; int ans = -0x3f3f3f3f;
	while(p)
	{
		if(Z[p].dat>=key) p = Z[p].ls;
		else
		{
			if(Z[p].dat>ans) ans = Z[p].dat;
			p = Z[p].rs;
		}
	}
	return ans;
}
int gethouji(int key)
{
	int p = rt; int ans = 0x3f3f3f3f;
	while(p)
	{
		if(Z[p].dat<=key) p = Z[p].rs;
		else 
		{
			if(Z[p].dat<ans) ans = Z[p].dat;
			p = Z[p].ls;
		}
	}
	return ans;
}
int main()
{
//	freopen("aha.out","w",stdout);
	srand(19360924);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int opt,x;
		scanf("%d%d",&opt,&x);
		if(opt==1) ins(x);
		else if(opt==2) del(x);
		else if(opt==3) printf("%d\n",getpaiming(x));
		else if(opt==4) printf("%d\n",Z[getk(x)].dat);
		else if(opt==5) printf("%d\n",getqianqu(x));
		else printf("%d\n",gethouji(x));
	}
}
 
posted @ 2018-07-21 12:52  Newuser233  阅读(10)  评论(0)    收藏  举报