[洛谷P3835]【模板】可持久化平衡树

题目大意:
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作(对于各个以往的历史版本):
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个,如果没有请忽略该操作)
3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数,如不存在输出-2147483647)
6. 求x的后继(后继定义为大于x,且最小的数,如不存在输出2147483647)
和原本平衡树不同的一点是,每一次的任何操作都是基于某一个历史版本,同时生成一个新的版本。(操作3, 4, 5, 6即保持原版本无变化)
每个版本的编号即为操作的序号(版本0即为初始状态,空树)。
解题思路:
可持久化平衡树,用非旋Treap实现。
和普通Treap其实没什么区别,主要是split和平常写的重量平衡树有点不同,然后每次要新建节点,其他都一样。

C++ Code:

#include<bits/stdc++.h>
#define N 500005
struct node{
    int r,ls,rs,s,sz;
}a[N*50];
int rt[N],cnt=0;
inline int readint(){
    int c=getchar(),d=0,b=0;
    for(;!isdigit(c);c=getchar())b=c=='-';
    for(;isdigit(c);c=getchar())d=(d<<3)+(d<<1)+(c^'0');
    return b?-d:d;
}
inline void update(int x){
    a[x].sz=a[a[x].ls].sz+a[a[x].rs].sz+1;
}
void split(int u,int k,int& x,int& y){
    if(!u)x=y=0;
    else{
        if(a[u].s<=k){
            a[x=++cnt]=a[u];
            split(a[x].rs,k,a[x].rs,y);
            update(x);
        }else{
            a[y=++cnt]=a[u];
            split(a[y].ls,k,x,a[y].ls);
            update(y);
        }
    }
}
int merge(int x,int y){
    if(!x||!y)return x|y;
    int u;
    if(a[x].r<a[y].r){
        a[u=++cnt]=a[x];
        a[u].rs=merge(a[u].rs,y);
    }else{
        a[u=++cnt]=a[y];
        a[u].ls=merge(x,a[u].ls);
    }
    update(u);
    return u;
}
void Insert(int& root,int w){
    int x,y,z;
    split(root,w,x,y);
    a[z=++cnt]=(node){rand(),0,0,w,1};
    root=merge(merge(x,z),y);
}
void Delete(int& root,int w){
    int x,y,z;
    split(root,w,x,y);
    split(x,w-1,x,z);
    if(a[z].s==w)
    root=merge(merge(x,merge(a[z].ls,a[z].rs)),y);else
    root=merge(merge(x,z),y);
}
int getpos(int now,int k){
    for(;;){
        if(k<=a[a[now].ls].sz)now=a[now].ls;
        if(k==a[a[now].ls].sz+1)return now;
        if(k>a[a[now].ls].sz)k-=a[a[now].ls].sz+1,now=a[now].rs;
    }
}
int kth(int rt,int w){
    int x,y,rank;
    split(rt,w-1,x,y);
    rank=a[x].sz+1;
    rt=merge(x,y);
    return rank;
}
int find(int rt,int w){
    return a[getpos(rt,w)].s;
}
int pre(int rt,int w){
    int x,y,ans;
    split(rt,w-1,x,y);
    if(!x)ans=-2147483647;else
    ans=a[x].sz;
    if(ans!=-2147483647)
    ans=find(x,ans);
    rt=merge(x,y);
    return ans;
}
int nxt(int rt,int w){
    int x,y,ans;
    split(rt,w,x,y);
    if(!y)ans=2147483647;else
    ans=a[y].sz;
    if(ans!=2147483647)
    ans=find(y,1);
    rt=merge(x,y);
    return ans;
}
int main(){
    srand(20170607);
    memset(rt,0,sizeof rt);
    memset(a,0,sizeof a);
    for(int T=readint(),now=1;now<=T;++now){
        int v=readint(),opt=readint(),x=readint();
        rt[now]=rt[v];
        if(opt==1)Insert(rt[now],x);else
        if(opt==2)Delete(rt[now],x);else
        if(opt==3)printf("%d\n",kth(rt[now],x));else
        if(opt==4)printf("%d\n",find(rt[now],x));else
        if(opt==5)printf("%d\n",pre(rt[now],x));else
        printf("%d\n",nxt(rt[now],x));
    }
    return 0;
}

 

posted @ 2018-04-16 19:13  Mrsrz  阅读(169)  评论(0编辑  收藏  举报