您的位置:首页 > 理论基础 > 数据结构算法

[BZOJ 3224]普通平衡树(忽然想要存个模板 Treap/Splay)

2017-03-09 08:47 561 查看

Description

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

1. 插入x数

2. 删除x数(若有多个相同的数,因只删除一个)

3. 查询x数的排名(若有多个相同的数,因输出最小的排名)

4. 查询排名为x的数

5. 求x的前驱(前驱定义为小于x,且最大的数)

6. 求x的后继(后继定义为大于x,且最小的数)

Solution

其实差不多是黄学长那个板子

Treap

对了bzoj上似乎用
srand(time(NUll))
会RE

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<ctime>
using namespace std;
int size=0,root=0,ans;
struct Node
{
int lch,rch;
int val,size,rank,w;
}tree[100005];
void update(int k)
{
tree[k].size=tree[tree[k].lch].size+tree[tree[k].rch].size+tree[k].w;
}
void leftRotate(int &k)
{
int t=tree[k].rch;
tree[k].rch=tree[t].lch;
tree[t].lch=k;
tree[t].size=tree[k].size;
update(k);
k=t;
}
void rightRotate(int &k)
{
int t=tree[k].lch;
tree[k].lch=tree[t].rch;
tree[t].rch=k;
tree[t].size=tree[k].size;
update(k);
k=t;
}
void _insert(int &k,int x)
{
if(k==0)
{
size++;k=size;
tree[k].size=tree[k].w=1;
tree[k].rank=rand();
tree[k].val=x;
return;
}
tree[k].size++;
if(x<tree[k].val)
{
_insert(tree[k].lch,x);
if(tree[k].rank<tree[tree[k].lch].rank)rightRotate(k);
}
else if(x>tree[k].val)
{
_insert(tree[k].rch,x);
if(tree[k].rank<tree[tree[k].rch].rank)leftRotate(k);
}
else if(tree[k].val==x)tree[k].w++;
}
void _delete(int &k,int x)
{
if(k==0)return;
if(tree[k].val==x)
{
if(tree[k].w>1)
{
tree[k].w--;tree[k].size--;return;
}
if(!tree[k].lch||!tree[k].rch)
k=tree[k].lch+tree[k].rch;
else if(tree[tree[k].lch].rank<tree[tree[k].rch].rank)
{
leftRotate(k);_delete(k,x);
}
else
{
rightRotate(k);_delete(k,x);
}
}
else if(tree[k].val>x)
{
tree[k].size--;_delete(tree[k].lch,x);
}
else
{
tree[k].size--;_delete(tree[k].rch,x);
}
}
int _queryRank(int k,int x)
{
if(k==0)return 0;
if(tree[k].val==x)return tree[tree[k].lch].size+1;
if(tree[k].val<x)return tree[tree[k].lch].size+tree[k].w+_queryRank(tree[k].rch,x);
else return _queryRank(tree[k].lch,x);
}
int _queryNum(int k,int x)
{
if(k==0)return 0;
if(x<=tree[tree[k].lch].size)return _queryNum(tree[k].lch,x);
else if(x>tree[tree[k].lch].size+tree[k].w)
{
return _queryNum(tree[k].rch,x-tree[tree[k].lch].size-tree[k].w);
}
else return tree[k].val;
}
void _queryPre(int k,int x)
{
if(k==0)return;
if(tree[k].val<x)
{
ans=tree[k].val;
_queryPre(tree[k].rch,x);
}
else _queryPre(tree[k].lch,x);
}
void _querySuc(int k,int x)
{
if(k==0)return;
if(tree[k].val>x)
{
ans=tree[k].val;
_querySuc(tree[k].lch,x);
}
else _querySuc(tree[k].rch,x);
}
int main()
{
//srand(time(NULL));
int n,opt,x;
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:_delete(root,x);break;
case 3:cout<<_queryRank(root,x)<<endl;break;
case 4:cout<<_queryNum(root,x)<<endl;break;
case 5:ans=0;_queryPre(root,x);cout<<ans<<endl;break;
case 6:ans=0;_querySuc(root,x);cout<<ans<<endl;break;
}
}
return 0;
}


Splay(Update)

bzoj这道用cin.cout也会RE啊QvQ

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
int root=0,siz=0,ans;
struct Node{
int ch[2],father;
int siz,val,w;
}tr[100005];
int read()
{
int f=1,x=0;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')f=-1;c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0';c=getchar();
}
return x*f;
}
void update(int k)
{
tr[k].siz=tr[tr[k].ch[0]].siz+tr[tr[k].ch[1]].siz+tr[k].w;
}
void rotate(int x,int &k)
{
int y=tr[x].father;
int z=tr[y].father;
int t=(tr[y].ch[0]==x)?0:1;
if(y==k)k=x;
else
{
if(tr[z].ch[0]==y)tr[z].ch[0]=x;
else tr[z].ch[1]=x;
}
tr[x].father=z;tr[y].father=x;
tr[tr[x].ch[t^1]].father=y;
tr[y].ch[t]=tr[x].ch[t^1];
tr[x].ch[t^1]=y;
update(y);update(x);
}
void splay(int x,int &k)
{
int y,z;
while(x!=k)
{
y=tr[x].father;z=tr[y].father;
if(y!=k)
{
if((tr[y].ch[0]==x)^(tr[z].ch[1]==y))
rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
void _insert(int &k,int x,int f)
{
if(!k)
{
siz++;k=siz;
tr[k].father=f;
tr[k].val=x;
tr[k].siz=tr[k].w=1;
tr[k].ch[0]=tr[k].ch[1]=0;
splay(k,root);
return;
}
tr[k].siz++;
if(x==tr[k].val)tr[k].w++;
else if(x>tr[k].val)_insert(tr[k].ch[1],x,k);
else _insert(tr[k].ch[0],x,k);
}
void _delete(int k,int x)
{
if(!k)return;
if(tr[k].val==x)
{
splay(k,root);
if(tr[k].w>1)
{
tr[k].w--;tr[k].siz--;
return;
}
if(tr[k].ch[0]==0||tr[k].ch[1]==0)
{
root=tr[k].ch[0]+tr[k].ch[1];
tr[root].father=0;
return;
}
int t=tr[k].ch[1];
while(tr[t].ch[0])t=tr[t].ch[0];
tr[t].ch[0]=tr[k].ch[0];
tr[tr[k].ch[0]].father=t;
root=tr[k].ch[1];
tr[root].father=0;
while(t!=root)update(t),t=tr[t].father;
update(root);
return;
}
tr[k].siz--;
if(tr[k].val>x)_delete(tr[k].ch[0],x);
else _delete(tr[k].ch[1],x);
}
int _queryRank(int k,int x)
{
if(!k)return 0;
if(tr[k].val==x)return tr[tr[k].ch[0]].siz+1;
if(tr[k].val<x)return tr[tr[k].ch[0]].siz+tr[k].w+_queryRank(tr[k].ch[1],x);
else return _queryRank(tr[k].ch[0],x);
}
int _queryNum(int k,int x)
{
if(!k)return 0;
if(x<=tr[tr[k].ch[0]].siz)return _queryNum(tr[k].ch[0],x);
else if(x>tr[tr[k].ch[0]].siz+tr[k].w)
{
return _queryNum(tr[k].ch[1],x-tr[tr[k].ch[0]].siz-tr[k].w);
}
else return tr[k].val;
}
void _queryPre(int k,int x)
{
if(!k)return;
if(tr[k].val<x)
{
ans=tr[k].val;
_queryPre(tr[k].ch[1],x);
}
else _queryPre(tr[k].ch[0],x);
}
void _querySuc(int k,int x)
{
if(!k)return;
if(tr[k].val>x)
{
ans=tr[k].val;
_querySuc(tr[k].ch[0],x);
}
else _querySuc(tr[k].ch[1],x);
}
int main()
{
int n,opt,x;
n=read();
for(int i=1;i<=n;i++)
{
opt=read();x=read();
switch(opt)
{
case 1:_insert(root,x,0);break;
case 2:_delete(root,x);break;
case 3:printf("%d\n",_queryRank(root,x));break;
case 4:printf("%d\n",_queryNum(root,x));break;
case 5:ans=0;_queryPre(root,x);printf("%d\n",ans);break;
case 6:ans=0;_querySuc(root,x);printf("%d\n",ans);break;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构