可持久化平衡树 LUOGU P-3835

/*
这道题一看可以知道是平衡树+持久化.如果是持久化,
那么我们就要保存历史信息,每次修改logn个点,所以内存要靠2nlogn.
split是把以i为根节点的子树分成两部分,一部分小于等于k,一部分大于k,必须保证其BST所有的性质
merge是合并以x为根节点和以y为根节点的两颗子树。
*/
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
struct node{
    int l,r;
    int v,rd,sum;
}a[N*50];
int cnt;
void update(int i){
    if(!i)return ;
    a[i].sum=a[a[i].l].sum+a[a[i].r].sum+1;
}
int newnode(int x){
    ++cnt;
    a[cnt].l=a[cnt].r=0;
    a[cnt].sum=1;a[cnt].v=x;
    a[cnt].rd=rand();
    return cnt;
}
int merge(int x,int y){//合并操作,按照treap的rd的优先级来合并(小跟堆或大根堆都行)
//这里是大根堆 
    if(!x||!y)return x+y;
    if(a[x].rd>a[y].rd){
        int p=++cnt;a[p]=a[x];
        a[p].r=merge(a[p].r,y);
        update(p);return p;
    }
    else {
        int p=++cnt;a[p]=a[y];
        a[p].l=merge(x,a[p].l);
        update(p);return p;
    }
}
void split(int now,int k,int &x,int &y){//把小于等于k的数放x子树里面,大于k的放y子树里面 
    if(now==0){x=y=0;return ;}
    if(a[now].v<=k){
        x=++cnt;a[x]=a[now];
        split(a[x].r,k,a[x].r,y);
        update(x);
    }
    else {
        y=++cnt;a[y]=a[now];
        split(a[y].l,k,x,a[y].l);
        update(y);
    }
}
void insert(int &root,int v){//插入一个新结点 
     int x=0,y=0,z=0;
     split(root,v-1,x,y);
     z=newnode(v);
     root=merge(merge(x,z),y);
}
void del(int &root,int v){//删除一个结点
    int x=0,y=0,z=0;
    split(root,v,x,z);
    split(x,v-1,x,y);
    y=merge(a[y].l,a[y].r);
    root=merge(merge(x,y),z);
}
int rank_value(int i,int k){
    if(k==a[a[i].l].sum+1)return a[i].v;
    if(k<=a[a[i].l].sum)return rank_value(a[i].l,k);
    return rank_value(a[i].r,k-a[a[i].l].sum-1);
}
int kth_rank(int &root,int v){//查询排名为x的数
    int x,y;
    split(root,v-1,x,y);
    int ans=a[x].sum+1;
    root=merge(x,y);
    return ans;
}
int pre(int &root,int v){//求前驱 
    int x,y,k;
    split(root,v-1,x,y);
    if(x==0)return -2147483647;
    k=a[x].sum;
    int ans=rank_value(x,k);
    root=merge(x,y);
    return ans;
}
int nex(int &root,int v){//求后驱
    int x,y,ans;
    split(root,v,x,y);
    if(y==0)return 2147483647;
    ans=rank_value(y,1);
    root=merge(x,y);
    return ans;
}
int n,root[N];
int main(){
    scanf("%d",&n);
    int x,y,op;
    for(int i=1;i<=n;i++){
    	scanf("%d%d%d",&x,&op,&y);
    	root[i]=root[x];
    	if(op==1)insert(root[i],y);
    	if(op==2)del(root[i],y);
    	if(op==3)printf("%d
",kth_rank(root[i],y));
    	if(op==4)printf("%d
",rank_value(root[i],y));
    	if(op==5)printf("%d
",pre(root[i],y));
    	if(op==6)printf("%d
",nex(root[i],y));
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/c201904xyorz/p/10222582.html