摘自 Hallmeow
支持以下操作:
1.插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
#define pos(i,a,b) for(int i=(a);i<=(b);i++)
#define pos2(i,a,b) for(int i=(a);i>=(b);i--)
#define N 500010
struct Treap
{
int l,r,w,v,size,rnd;
//v为实际数值;rnd为优先级;size为以它为根的子树大小;w为自身节点存的数的个数(数据可以有多个重复的数)
}tree[N];
int n;
int root,size;
void update(int k)
{
tree[k].size=tree[tree[k].l].size+tree[tree[k].r].size+tree[k].w;
//更新子树大小
}
void rturn(int &k)
{
int t=tree[k].l;
tree[k].l=tree[t].r;
tree[t].r=k;
tree[t].size=tree[k].size;
update(k);
k=t;
}//右旋转
void lturn(int &k)
{
int t=tree[k].r;
tree[k].r=tree[t].l;
tree[t].l=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].w=tree[k].size=1;
tree[k].v=x;
tree[k].rnd=rand();//随机数
return;
}
tree[k].size++;
if(tree[k].v==x)//如果有多个,w++
tree[k].w++;
else
{
if(tree[k].v<x)//满足二叉排序树性质
{
insert(tree[k].r,x);
if(tree[tree[k].r].rnd<tree[k].rnd)
lturn(k);//维护堆性质,左旋转
}
else
{
insert(tree[k].l,x);
if(tree[tree[k].l].rnd<tree[k].rnd)
rturn(k);
}
}
}
int tmp;
void query_pro(int k,int x)
{
if(k==0)
return;
if(x>tree[k].v)
{
tmp=k;//不断更新过程。数值小于目标值,去右子树里找 ,找到第一个比它大的值。此时更新结果即为比它小的最大的值
query_pro(tree[k].r,x);
}
else
query_pro(tree[k].l,x);
}
void query_sub(int k,int x)
{
if(k==0)
return;
if(x<tree[k].v)//与上面同理
{
tmp=k;
query_sub(tree[k].l,x);
}
else
query_sub(tree[k].r,x);
}
void del(int &k,int x)
{
if(k==0)
return;
if(tree[k].v==x)
{
if(tree[k].w>1)//若不止相同值的个数有多个,删去一个
{
tree[k].w--;
tree[k].size--;
return;
}
if(tree[k].l*tree[k].r==0)//有一个儿子为空
k=tree[k].l+tree[k].r;
else
{
if(tree[tree[k].l].rnd<tree[k].rnd)
{
rturn(k);
del(k,x);
}
else
{
lturn(k);
del(k,x);
}
}
}
else
{
if(x>tree[k].v)
{
tree[k].size--;
del(tree[k].r,x);
}
else
{
tree[k].size--;
del(tree[k].l,x);
}
}
}
int query_rank(int k,int x)
{
if(k==0)
return 0;
if(tree[k].v==x)
return tree[tree[k].l].size+1;//找到目标值,左子树都比它小,左子树大小+1即为它的排名
else
{
if(x>tree[k].v)
return tree[tree[k].l].size+tree[k].w+query_rank(tree[k].r,x);
else
return query_rank(tree[k].l,x);
}
}
int query_num(int k,int x)
{
if(k==0)
return 0;
if(x<=tree[tree[k].l].size)
return query_num(tree[k].l,x);
else
if(x>tree[tree[k].l].size+tree[k].w)
return query_num(tree[k].r,x-tree[tree[k].l].size-tree[k].w);
else
return tree[k].v;
}
int main()
{
//freopen("phs.in","r",stdin);
//freopen("phs.out","w",stdout);
scanf("%d",&n);
int opt,x;
pos(i,1,n)
{
scanf("%d%d",&opt,&x);
switch(opt)
{
case 1:insert(root,x);break;
case 2:del(root,x);break;
case 3:printf("%d\n",query_rank(root,x));break;
case 4:printf("%d\n",query_num(root,x));break;
case 5:tmp=0;query_pro(root,x);printf("%d\n",tree[tmp].v);break;
case 6:tmp=0;query_sub(root,x);printf("%d\n",tree[tmp].v);break;
}
}
//while(1);
return 0;
}
Splay指针版:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<stack>
#define INF 2100000000
#define ll long long
#define clr(x) memset(x,0,sizeof(x))
#define maxclr(x) memset(x,127,sizeof(x))
using namespace std;
inline int read()
{
char c;
int ret=0,b=1;
while(!(c>='0'&&c<='9'))
{
if(c=='-')b=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
ret=(c-'0')+(ret<<1)+(ret<<3);
c=getchar();
}
return ret*b;
}
#define M 100005
struct tree2
{
tree2 *son[2],*fa;
int n,siz,num;
}*root,dizhi[M],*null,*Null;
#define lson son[0]
#define rson son[1]
int n,t;
tree2 *newtree(tree2 *fa,int x)
{
tree2 *tree=&dizhi[t++];
tree->siz=tree->num=1;
tree->lson=tree->rson=Null;
tree->n=x;
tree->fa=fa;
return tree;
}
void pushup(tree2 *tree)
{
if(tree==null)return ;
tree->siz=tree->num+tree->lson->siz+tree->rson->siz;
}
void rotate(tree2 *tree,int x)
{
tree2 *fa=tree->fa;
fa->son[x^1]=tree->son[x];
if(tree->son[x]!=Null)tree->son[x]->fa=fa;
fa->fa->son[fa->fa->son[1]==fa]=tree;
tree->fa=fa->fa;
fa->fa=tree;
tree->son[x]=fa;
pushup(fa);
}
void splay(tree2 *tree,tree2 *goal)
{
if(tree==goal)return ;
while(tree->fa!=goal)
{
tree2 *fa=tree->fa,*gfa=fa->fa;
if(gfa==goal)
{
rotate(tree,fa->son[0]==tree);
break;
}
int x=gfa->son[1]==fa;
if((fa->son[1]==tree)==x)
{
rotate(fa,x^1);
rotate(tree,x^1);
}
else
{
rotate(tree,x);
rotate(tree,x^1);
}
}
pushup(tree);
if(goal==null)root=tree;
}
void insert(int k)
{
if(root==NULL)
{
root=newtree(null,k);
return ;
}
tree2 *temp=root;
while(temp->son[temp->n<k]!=Null)
{
if(temp->n==k)break;
temp=temp->son[temp->n<k];
}
if(temp->n==k)
{
temp->siz++;
temp->num++;
splay(temp,null);
return;
}
temp->son[temp->n<k]=newtree(temp,k);
splay(temp->son[temp->n<k],null);
}
tree2 *find(int k)
{
tree2 *temp=root;
while(temp->son[temp->n<k])
{
if(temp->n==k)break;
temp=temp->son[temp->n<k];
}
return temp;
}
void dele(int k)
{
tree2 *temp=find(k);
if(temp->num!=1)
{
temp->siz--;
temp->num--;
splay(temp,null);
return ;
}
int x=temp->fa->son[1]==temp;
if(temp->lson==Null)
if(temp->rson==Null)
temp->fa->son[x]=Null;
else
{
temp->fa->son[x]=temp->rson;
temp->rson->fa=temp->fa;
}
else
if(temp->rson==Null)
{
temp->fa->son[x]=temp->lson;
temp->lson->fa=temp->fa;
}
else
{
tree2 *tree=temp->lson;
temp->fa->son[x]=temp->lson;
temp->lson->fa=temp->fa;
while(tree->rson!=Null)tree=tree->rson;
tree->rson=temp->rson;
temp->rson->fa=tree;
pushup(tree);
splay(tree,null);
return ;
}
pushup(temp->fa);
splay(temp->fa,null);
}
int query(int k)
{
tree2 *temp=root;
int num=0;
while(temp->n!=k)
{
int x=temp->n<k;
if(x==1)num+=temp->lson->siz+temp->num;
temp=temp->son[x];
}
num+=temp->lson->siz;
splay(temp,null);
return num+1;
}
int query_rank(int k)
{
tree2 *temp=root;
int num=temp->lson->siz;
while(!(k>num&&k<=num+temp->num))
{
if(k>num)
{
k-=num+temp->num;
temp=temp->rson;
}
else temp=temp->lson;
num=temp->lson->siz;
}
splay(temp,null);
return temp->n;
}
int get_pre(int k)
{
tree2 *tree=root;
int ret=0;
while(tree->lson!=Null||tree->rson!=Null)
{
if(tree->n>=k)
if(tree->lson!=Null)tree=tree->lson;
else break;
else
{
ret=max(ret,tree->n);
if(tree->rson!=Null)tree=tree->rson;
else break;
}
}
if(tree->n<k)ret=max(ret,tree->n);
splay(tree,null);
return ret;
}
int get_next(int k)
{
tree2 *tree=root;
int ret=INF;
while(tree->lson!=Null||tree->rson!=Null)
{
if(tree->n<=k)
if(tree->rson!=Null)tree=tree->rson;
else break;
else
{
ret=min(ret,tree->n);
if(tree->lson!=Null)tree=tree->lson;
else break;
}
}
if(tree->n>k)ret=min(ret,tree->n);
splay(tree,null);
return ret;
}
int main()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
n=read();
Null=&dizhi[t++];null=&dizhi[t++];
for(int i=1;i<=n;i++)
{
int c=read(),x=read();
switch(c)
{
case 1:insert(x);break;
case 2:dele(x);break;
case 3:printf("%d\n",query(x));break;
case 4:printf("%d\n",query_rank(x));break;
case 5:printf("%d\n",get_pre(x));break;
case 6:printf("%d\n",get_next(x));break;
}
}
return 0;
}