3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 6588 Solved: 2722
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.每个数的数据范围:[-1e7,1e7]
Source
平衡树
treap模板题。。
附上本蒟蒻的代码:
#include<cstdio>
#include<iostream>
#include<cstdlib>
using namespace std;
struct data
{
int l,r,v,size,rnd,w;
}node[100001];
int n,size,root,ans;
int read()
{
int w=0,c=1; char ch=getchar();
while (ch<'0' || ch>'9')
{
if (ch=='-') c=-1;
ch=getchar();
}
while (ch>='0' && ch<='9')
w=w*10+ch-'0',ch=getchar();
return w*c;
}
void update(int s)
{
node[s].size=node[node[s].l].size+node[node[s].r].size+node[s].w;
}
void rturn(int &s)
{
int t=node[s].l;
node[s].l=node[t].r,node[t].r=s,node[t].size=node[s].size,update(s),s=t;
}
void lturn(int &s)
{
int t=node[s].r;
node[s].r=node[t].l,node[t].l=s,node[t].size=node[s].size,update(s),s=t;
}
void insert(int &s,int x)
{
if (!s) {size++,s=size,node[s].size=node[s].w=1,node[s].v=x,node[s].rnd=rand();return;}
node[s].size++;
if (node[s].v==x)
node[s].w++;
else
if (x>node[s].v)
{
insert(node[s].r,x);
if (node[node[s].r].rnd<node[s].rnd) lturn(s);
}
else
{
insert(node[s].l,x);
if (node[node[s].l].rnd<node[s].rnd) rturn(s);
}
}
void del(int &s,int x)
{
if (!s) return;
if (node[s].v==x)
{
if (node[s].w>1) {node[s].w--,node[s].size--;return;}
if (node[s].l*node[s].r==0) s=node[s].l+node[s].r;
else if (node[node[s].l].rnd<node[node[s].r].rnd) rturn(s),del(s,x);
else lturn(s),del(s,x);
}
else if (x>node[s].v) node[s].size--,del(node[s].r,x);
else node[s].size--,del(node[s].l,x);
}
int queryrank(int s,int x)
{
if (!s) return 0;
if (node[s].v==x) return node[node[s].l].size+1;
else if (x>node[s].v) return node[node[s].l].size+node[s].w+queryrank(node[s].r,x);
else return queryrank(node[s].l,x);
}
int querynum(int s,int x)
{
if (!s) return 0;
if (x<=node[node[s].l].size) return querynum(node[s].l,x);
else if (x>node[node[s].l].size+node[s].w) return querynum(node[s].r,x-node[node[s].l].size-node[s].w);
else return node[s].v;
}
void querypred(int s,int x)
{
if (!s) return;
if (node[s].v<x) ans=s,querypred(node[s].r,x);
else querypred(node[s].l,x);
}
void querysucc(int s,int x)
{
if (!s) return;
if (node[s].v>x) ans=s,querysucc(node[s].l,x);
else querysucc(node[s].r,x);
}
int main()
{
int p,x,i;
n=read();
for (i=1;i<=n;i++)
{
p=read(),x=read();
switch (p)
{
case 1:insert(root,x);break;
case 2:del(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;querypred(root,x);printf("%d\n",node[ans].v);break;
case 6:ans=0;querysucc(root,x);printf("%d\n",node[ans].v);break;
}
}
return 0;
}