zoukankan      html  css  js  c++  java
  • 可持久化平衡树 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;
    }
    

      

  • 相关阅读:
    vue.nextTick()方法简单理解
    vue中 hash和history的区别
    Set,Map一些常见的遍历方法以及转化方法
    vue中import和require的用法
    $route和 $router的区别是什么
    vue vmodel的总结
    vue router的钩子函数总结
    了解promise和async await的区别
    ZOJ 1642 Match for Bonus
    UVA 10003 Cutting Sticks
  • 原文地址:https://www.cnblogs.com/c201904xyorz/p/10222582.html
Copyright © 2011-2022 走看看