LG3369 模板普通平衡树
Posted autoint
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LG3369 模板普通平衡树相关的知识,希望对你有一定的参考价值。
题意
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
- 插入x数
- 删除x数(若有多个相同的数,因只删除一个)
- 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
- 查询排名为x的数
- 求x的前驱(前驱定义为小于x,且最大的数)
- 求x的后继(后继定义为大于x,且最小的数)
(n leq 10^5)
分析
用范浩强Treap实现。具体原理:
代码
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#pragma GCC optimize ("O0")
using namespace std;
template<class T> inline T read(T&x)
{
T data=0;
int w=1;
char ch=getchar();
while(!isdigit(ch))
{
if(ch==‘-‘)
w=-1;
ch=getchar();
}
while(isdigit(ch))
data=10*data+ch-‘0‘,ch=getchar();
return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff;
const int MAXN=1e5+7;
int sz;
struct Treap
{
int val[MAXN],pri[MAXN];
int ch[MAXN][2],siz[MAXN];
void pushup(int x)
{
siz[x]=siz[ch[x][0]]+1+siz[ch[x][1]];
}
int new_node(int v)
{
val[++sz]=v,
pri[sz]=rand()<<15|rand();
ch[sz][0]=ch[sz][1]=0,
siz[sz]=1;
return sz;
}
int merge(int x,int y)
{
if(!x||!y)
return x+y;
if(pri[x]<pri[y])
{
ch[x][1]=merge(ch[x][1],y);
pushup(x);
return x;
}
else
{
ch[y][0]=merge(x,ch[y][0]);
pushup(y);
return y;
}
}
void split(int now,int v,int&x,int&y)
{
if(!now)
x=y=0;
else
{
if(val[now]<=v)
{
x=now,split(ch[now][1],v,ch[now][1],y);
}
else
{
y=now,split(ch[now][0],v,x,ch[now][0]);
}
pushup(now);
}
}
void ins(int&now,int v)
{
int x,y;
split(now,v,x,y);
now=merge(merge(x,new_node(v)),y);
}
void del(int&now,int v)
{
int x,y,z;
split(now,v,x,z);
split(x,v-1,x,y);
y=merge(ch[y][0],ch[y][1]);
now=merge(merge(x,y),z);
}
int rank(int&now,int v)
{
int x,y;
split(now,v-1,x,y);
int ans=siz[x]+1;
now=merge(x,y);
return ans;
}
int kth(int now,int k)
{
while(1)
{
if(k<=siz[ch[now][0]])
now=ch[now][0];
else if(k==siz[ch[now][0]]+1)
return now;
else
k-=siz[ch[now][0]]+1,now=ch[now][1];
}
}
int pre(int&now,int v)
{
int x,y;
split(now,v-1,x,y);
int ans=kth(x,siz[x]);
now=merge(x,y);
return ans;
}
int suc(int&now,int v)
{
int x,y;
split(now,v,x,y);
int ans=kth(y,1);
now=merge(x,y);
return ans;
}
}T;
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
srand(20030506);
int root=0;
int n;
read(n);
while(n--)
{
static int opt,x;
read(opt);read(x);
if(opt==1) // insert
{
T.ins(root,x);
}
else if(opt==2) // delete
{
T.del(root,x);
}
else if(opt==3) // rank
{
printf("%d
",T.rank(root,x));
}
else if(opt==4) // kth
{
printf("%d
",T.val[T.kth(root,x)]);
}
else if(opt==5) // precursor
{
printf("%d
",T.val[T.pre(root,x)]);
}
else // successor
{
printf("%d
",T.val[T.suc(root,x)]);
}
}
// fclose(stdin);
// fclose(stdout);
return 0;
}
以上是关于LG3369 模板普通平衡树的主要内容,如果未能解决你的问题,请参考以下文章