3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 20192 Solved: 8907
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.每个数的数据范围:[-2e9,2e9]
Source
题解
可以写Treap,也可以写spaly。
如果在洛谷里评测发现最后一个点过不去,很可能是因为INF开小了或者是没考虑负数。
代码
Treap(C++)
#include<ctime>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5+5,M=10000000,INF=((long long)1<<31)-1;
int n,siz=1;
int Ran(int x){return (rand()<<16|rand()<<1|(rand()&1))%x;}
struct nod{
//w表示点的值,s表示个点的数,tem表示子树上的节点树,id表示优先级
//son表示儿子节点,sum表示下一个新节点的号码(已经诞生了的节点个数)
int w,s,tem,id,son[2];
void giv(int t1,int t2,int t3,int t4,int t5,int t6)
{
w=t1;s=t2;tem=t3;id=t4;son[0]=t5;son[1]=t6;
}
}a[maxn];
int Bmin(int x,int y){return a[x].w<a[y].w? x:y;}
//修正子节点个数
void Updata(int x){a[x].tem=a[x].s+a[a[x].son[0]].tem+a[a[x].son[1]].tem;}
//旋转,p=0/1表示左转/右转
void Rotat(int &x,int p)
{
int y=a[x].son[p^1];
a[x].son[p^1]=a[y].son[p];
a[y].son[p]=x;
a[y].tem=a[x].tem;
Updata(x);x=y;
}
//插入一个节点
void Insert(int &x,int num)
{
if (!x){x=++siz;a[x].giv(num,1,1,Ran(M),0,0);return;}
a[x].tem++;
if (num<a[x].w)
{
Insert(a[x].son[0],num);
if (a[x].id>a[a[x].son[0]].id) Rotat(x,1);
}else
if (num>a[x].w)
{
Insert(a[x].son[1],num);
if (a[x].id>a[a[x].son[1]].id) Rotat(x,0);
}else a[x].s++;
}
void del(int &x,int num)
{
if (!x) return;
if (num<a[x].w) a[x].tem--,del(a[x].son[0],num);else
if (num>a[x].w) a[x].tem--,del(a[x].son[1],num);else
if (a[x].w==num)
{
if (a[x].s>1) {a[x].s--;a[x].tem--;return;}
if (a[x].son[0]&&a[x].son[1])
{
if (a[a[x].son[0]].id<a[a[x].son[1]].id) Rotat(x,1),del(x,num);
else Rotat(x,0),del(x,num);
}else x=a[x].son[0]+a[x].son[1];
}
}
int query_paimi(int x,int num)
{
if (!x) return 0;
if (a[x].w==num) return a[a[x].son[0]].tem+1;else
if (a[x].w>num) return query_paimi(a[x].son[0],num);else
return a[a[x].son[0]].tem+a[x].s+query_paimi(a[x].son[1],num);
}
int query_dinmin(int x,int num)
{
if (!x) return 0;
if (num<=a[a[x].son[0]].tem) return query_dinmin(a[x].son[0],num);else
if (num>a[a[x].son[0]].tem+a[x].s) return query_dinmin(a[x].son[1],num-a[a[x].son[0]].tem-a[x].s);else
return a[x].w;
}
int query_qianq(int x,int num)
{
if (!x) return -INF;
if (num>a[x].w) return max(a[x].w,query_qianq(a[x].son[1],num));
else return query_qianq(a[x].son[0],num);
}
int query_houji(int x,int num)
{
if (!x) return INF;
if (num<a[x].w) return min(a[x].w,query_houji(a[x].son[0],num));
else return query_houji(a[x].son[1],num);
}
int Read()
{
int ret=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
int main()
{
srand((unsigned)time(0));
n=Read();int pd,x,rot=0;
for (int i=1;i<=n;i++)
{
pd=Read();x=Read();
switch(pd)
{
case 1:{Insert(rot,x);break;}
case 2:{del(rot,x);break;}
case 3:{printf("%d\n",query_paimi(rot,x));break;}
case 4:{printf("%d\n",query_dinmin(rot,x));break;}
case 5:{printf("%d\n",query_qianq(rot,x));break;}
case 6:{printf("%d\n",query_houji(rot,x));break;}
}
}
return 0;
}