【BZOJ3224】普通平衡树

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/doyouseeman/article/details/52049675

Description

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)

Solution

这是一道练习treap的模板题,经典题,好题,码农题……
都是一些treap的基本,简单操作。
参见treap复习小记

Code

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=100007;
int i,j,k,l,n,m,ans,x,num,op;
int t[maxn][2];
int size[maxn],sum[maxn],key[maxn],sam[maxn],root;
void update(int x){
    size[x]=size[t[x][0]]+size[t[x][1]]+sam[x];
}
void rotate(int &x,int z){
    int y=t[x][z];
    t[x][z]=t[y][1-z];
    t[y][1-z]=x;
    update(x);update(y);
    x=y; 
} 
void insert(int &x,int y){
    if(!x){
        x=++num;size[x]=1;sam[x]=1;
        key[x]=rand();sum[x]=y;
        return;
    }
    size[x]++;
    if(sum[x]==y)sam[x]++;
    else if(y>sum[x]){
        insert(t[x][1],y);
        if(key[t[x][1]]<key[x])rotate(x,1);
    }
    else{
        insert(t[x][0],y);
        if(key[t[x][0]]>key[x])rotate(x,0);
    }
}
void dele(int &x,int y){
    if(!x)return;
    if(sum[x]==y){
        if(sam[x]>1){
            sam[x]--;size[x]--;return;
        }
        if(!(t[x][0]*t[x][1]))x=t[x][0]+t[x][1];
        else{
            if(key[t[x][0]]<key[t[x][1]])rotate(x,0),dele(x,y);
            else rotate(x,1),dele(x,y);
        }
    }
    else if(y>sum[x])size[x]--,dele(t[x][1],y);
    else size[x]--,dele(t[x][0],y);
}
int posnum(int x,int y){
    if(!x)return 0;
    if(sum[x]==y)return size[t[x][0]]+1;
    else if(sum[x]<y)return posnum(t[x][1],y)+sam[x]+size[t[x][0]];
    else return posnum(t[x][0],y);
}
int posrank(int x,int y){
    if(!x)return 0;
    if(size[t[x][0]]>=y)return posrank(t[x][0],y);
    else if(size[t[x][0]]+sam[x]<y)posrank(t[x][1],y-size[t[x][0]]-sam[x]);
    else return sum[x];
}
void pospre(int x,int y){
    if(!x)return;
    if(sum[x]<y)ans=sum[x],pospre(t[x][1],y);
    else pospre(t[x][0],y);    
}
void possub(int x,int y){
    if(!x)return;
    if(sum[x]>y)ans=sum[x],possub(t[x][0],y);
    else possub(t[x][1],y);    
}
int main(){
    scanf("%d",&n);
    fo(i,1,n){
        scanf("%d%d",&op,&x);
        switch(op){
            case 1:insert(root,x);break;
            case 2:dele(root,x);break;
            case 3:printf("%d\n",posnum(root,x));break;
            case 4:printf("%d\n",posrank(root,x));break;
            case 5:ans=0;pospre(root,x);printf("%d\n",ans);break;
            case 6:ans=0;possub(root,x);printf("%d\n",ans);break;
        }
    }
}
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页