BZOJ 3224 普通平衡树

Posted on 2015-12-13 18:27  ziliuziliu  阅读(174)  评论(0编辑  收藏  举报

这个是第一份完整的treap代码。嗯。。。虽然抄的百度的版,但还是不错的。

!bzoj上不能用srand。

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstdlib>
using namespace std;
struct treap
{
int left,right,value;
int fix,w,size;
}tr[100005];
int n,opt,x,ans,root=-1,cnt=0;
void update(int k)
{
tr[k].size=tr[tr[k].left].size+tr[tr[k].right].size+tr[k].w;
}
void lturn(int &k)
{
int t=tr[k].right;
tr[t].size=tr[k].size;
tr[k].right=tr[t].left;
tr[t].left=k;update(k);
k=t;
}
void rturn(int &k)
{
int t=tr[k].left;
tr[t].size=tr[k].size;
tr[k].left=tr[t].right;
tr[t].right=k;update(k);
k=t;
}
void insert(int &k,int x)
{
if (k==-1)
{
cnt++;
tr[cnt].left=-1;tr[cnt].right=-1;
tr[cnt].value=x;tr[cnt].fix=rand();
tr[cnt].w=1;tr[cnt].size=1;k=cnt;
return;
}
tr[k].size++;
if (tr[k].value==x) tr[k].w++;
else if (tr[k].value>x)
{
insert(tr[k].left,x);
if (tr[tr[k].left].fix<tr[k].fix) rturn(k);
}
else
{
insert(tr[k].right,x);
if (tr[tr[k].right].fix<tr[k].fix) lturn(k);
}
}
void del(int &k,int x)
{
if (k==-1) return;
if (tr[k].value==x)
{
if (tr[k].w>1)
{
tr[k].w--;tr[k].size--;
return;
}
if (tr[k].left==-1) k=tr[k].right;
else if (tr[k].right==-1) k=tr[k].left;
else if (tr[tr[k].left].fix<tr[tr[k].right].fix)
{
rturn(k);
del(k,x);
}
else
{
lturn(k);
del(k,x);
}
}
else if (tr[k].value<x)
{
tr[k].size--;
del(tr[k].right,x);
}
else
{
tr[k].size--;
del(tr[k].left,x);
}
}
int rank(int &k,int x)
{
if (k==-1) return 0;
if (tr[k].value==x) return tr[tr[k].left].size+1;
else if (x<tr[k].value) return rank(tr[k].left,x);
else return tr[tr[k].left].size+tr[k].w+rank(tr[k].right,x);
}
int num(int &k,int x)
{
if (k==-1) return 0;
if (x<=tr[tr[k].left].size)
return num(tr[k].left,x);
else if (x>tr[tr[k].left].size+tr[k].w)
return num(tr[k].right,x-tr[tr[k].left].size-tr[k].w);
else return tr[k].value;
}
void pro(int k,int x)
{
if (k==-1) return;
if (tr[k].value<x)
{
ans=k;
pro(tr[k].right,x);
}
else pro(tr[k].left,x);
}
void sub(int k,int x)
{
if (k==-1) return;
if (tr[k].value>x)
{
ans=k;
sub(tr[k].left,x);
}
else sub(tr[k].right,x);
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d%d",&opt,&x);
switch (opt)
{
case 1:insert(root,x);break;
case 2:del(root,x);break;
case 3:printf("%d\n",rank(root,x));break;
case 4:printf("%d\n",num(root,x));break;
case 5:ans=0;pro(root,x);printf("%d\n",tr[ans].value);break;
case 6:ans=0;sub(root,x);printf("%d\n",tr[ans].value);break;
}
}
return 0;
}