• [bzoj3196][Tyvj 1730][二逼平衡树] (线段树套treap)


    Description

    您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
    1.查询k在区间内的排名
    2.查询区间内排名为k的值
    3.修改某一位值上的数值
    4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
    5.查询k在区间内的后继(后继定义为大于x,且最小的数)

    Input

    第一行两个数 n,m 表示长度为n的有序序列和m个操作
    第二行有n个数,表示有序序列
    下面有m行,opt表示操作标号
    若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
    若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
    若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
    若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
    若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继

    Output

    对于操作1,2,4,5各输出一行,表示查询结果

    Sample Input

    9 6
    4 2 2 1 9 4 0 1 1
    2 1 4 3
    3 4 10
    2 1 4 3
    1 2 5 9
    4 3 9 5
    5 2 8 5

    Sample Output

    2
    4
    3
    4
    9

    HINT

    1.n和m的数据范围:n,m<=50000

    2.序列中每个数的数据范围:[0,1e8]

    3.虽然原题没有,但事实上5操作的k可能为负数

    Solution

    #include <stdio.h>
    #include <stdlib.h>
    #define N 50010
    #define inf 0x7fffffff
    #define opp 0x80000000
    #define mid ((x>>1)+(y>>1)+(x&y&1))
    #define dmax(x,y) ((x)>(y)?(x):(y))
    #define dmin(x,y) ((x)<(y)?(x):(y))
    #define RG register
    #define inline __inline__ __attribute__((always_inline))
    
    inline int Rin(){
        RG int x=0,c=getchar(),f=1;
        for(;c<48||c>57;c=getchar())
            if(!(c^45))f=-1;
        for(;c>47&&c<58;c=getchar())
            x=(x<<1)+(x<<3)+c-48;
        return x*f;
    }
    
    int n,m,a[N];
    
    namespace Seg{
        struct Treap{
            struct Nt{
                Nt*ch[2];
                int s,w,v,r;
    
                Nt(RG int v,RG Nt*_) : v(v),r(rand()) {
                    s=w=1;
                    ch[0]=ch[1]=_;
                }
    
                inline void maintain(){
                    s=w+ch[0]->s+ch[1]->s;
                }
            }*root,*null;
    
            Treap(){
                null=new Nt(0,0x0);
                null->s=null->w=0;
                null->r=inf;
                null->ch[0]=null->ch[1]=null;
                root=null;
            }
    
            void rotate(RG Nt*&o,RG int d){
                Nt*k=o->ch[1^d];
                o->ch[1^d]=k->ch[d];
                k->ch[d]=o;
                o->maintain();
                k->maintain();
                o=k;
            }
    
            void insert(RG Nt*&o,RG int v){
                if(o==null){
                    o=new Nt(v,null);
                    return;
                }
                o->s++;
                if(v==o->v)
                    o->w++;
                else{
                    RG int d=v > o->v;
                    insert(o->ch[d],v);
                    if(o->ch[d]->r < o->r)
                        rotate(o,1^d);
                }
            }
    
            void remove(RG Nt*&o,RG int v){
                if(o==null)
                    return;
                if(o->v==v){
                    if(o->w>1){
                        o->s--;
                        o->w--;
                        return;
                    }
                    if(o->ch[0]!=null && o->ch[1]!=null){
                        RG int d=o->ch[0]->r > o->ch[1]->r;
                        rotate(o,d);
                        remove(o->ch[d],v);
                    }
                    else o=o->ch[o->ch[0]==null];
                }
                else{
                    o->s--;
                    remove(o->ch[o->v < v],v);
                }
                if(o!=null)
                    o->maintain();
            }
    
            inline int pre(RG int v){
                RG int ans=opp;
                for(RG Nt*o=root;o!=null;)
                    v > o->v ? (ans=dmax(ans,o->v),o=o->ch[1]) : o=o->ch[0];
                return ans;
            }
    
            inline int nxt(RG int v){
                RG int ans=inf;
                for(RG Nt*o=root;o!=null;)
                    v < o->v ? (ans=dmin(ans,o->v),o=o->ch[0]) : o=o->ch[1];
                return ans;
            }
    
            inline int rank(RG int v){
                RG int ans=0;
                for(Nt*o=root;o!=null;){
                    RG int d= v==o->v? -1 : (o->v < v);
                    if(d==-1){
                        ans+=o->ch[0]->s;
                        break;
                    }
                    d?(ans+=o->ch[0]->s+o->w,o=o->ch[1]):o=o->ch[0];
                }
                return ans;
            }
        }rt[N<<2];
    
        void build(RG int x,RG int y,RG int k){
            for(RG int i=x;i<=y;i++)
                rt[k].insert(rt[k].root,a[i]);
            if(x<y){
                build(x,mid,k<<1);
                build(mid+1,y,k<<1|1);
            }
        }
    
        void modify(RG int x,RG int y,RG int k,RG int pos,RG int num){
            rt[k].remove(rt[k].root,a[pos]);
            rt[k].insert(rt[k].root,num);
            if(x<y)
                pos<=mid ? modify(x,mid,k<<1,pos,num):
                    modify(mid+1,y,k<<1|1,pos,num);
        }
    
        int getrank(RG int x,RG int y,RG int k,RG int l,RG int r,RG int num){
            if(x==l && y==r)
                return rt[k].rank(num);
            if(r<=mid)
                return getrank(x,mid,k<<1,l,r,num);
            if(l>mid)
                return getrank(mid+1,y,k<<1|1,l,r,num);
            return getrank(x,mid,k<<1,l,mid,num)+getrank(mid+1,y,k<<1|1,mid+1,r,num);
        }
    
        int getpre(RG int x,RG int y,RG int k,RG int l,RG int r,RG int num){
            if(x==l && y==r)
                return rt[k].pre(num);
            if(r<=mid)
                return getpre(x,mid,k<<1,l,r,num);
            if(l>mid)
                return getpre(mid+1,y,k<<1|1,l,r,num);
            return dmax(getpre(x,mid,k<<1,l,mid,num),getpre(mid+1,y,k<<1|1,mid+1,r,num));
        }
    
        int getnxt(RG int x,RG int y,RG int k,RG int l,RG int r,RG int num){
            if(x==l && y==r)
                return rt[k].nxt(num);
            if(r<=mid)
                return getnxt(x,mid,k<<1,l,r,num);
            if(l>mid)
                return getnxt(mid+1,y,k<<1|1,l,r,num);
            return dmin(getnxt(x,mid,k<<1,l,mid,num),getnxt(mid+1,y,k<<1|1,mid+1,r,num));
        }
    
        inline int getkth(RG int l,RG int r,RG int k){
            RG int x=0,y=1e8;
            while(x<=y)
                getrank(1,n,1,l,r,mid) < k ?
                    x=mid+1:
                    y=mid-1;
            if(getrank(1,n,1,l,r,x)>=k)
                x=getpre(1,n,1,l,r,x);
            return x;
        }
    }
    
    int main(){
        srand('K'+'a'+'i'+'b'+'a');
        n=Rin(),m=Rin();
        for(int i=1;i<=n;i++)
            a[i]=Rin();
        Seg::build(1,n,1);
        while(m--){
            RG int x,y,k,c=Rin();
            switch(c){
                case 1 :
                    x=Rin(),y=Rin(),k=Rin();
                    printf("%d
    ",Seg::getrank(1,n,1,x,y,k)+1);
                    break;
                case 2 :
                    x=Rin(),y=Rin(),k=Rin();
                    printf("%d
    ",Seg::getkth(x,y,k));
                    break;
                case 3 :
                    x=Rin(),k=Rin();
                    Seg::modify(1,n,1,x,k);
                    a[x]=k;
                    break;
                case 4 :
                    x=Rin(),y=Rin(),k=Rin();
                    printf("%d
    ",Seg::getpre(1,n,1,x,y,k));
                    break;
                case 5 :
                    x=Rin(),y=Rin(),k=Rin();
                    printf("%d
    ",Seg::getnxt(1,n,1,x,y,k));
                    break;
                default : break;
            }
        }
        return 0;
    }
  • 相关阅读:
    C# 监测每个方法的执行次数和占用时间(测试1)
    C# 依赖注入那些事儿
    SQL Server GROUP BY 后 拼接 字符串
    C# 根据Excel生成树
    C# 反射赋值
    C# 集合转换为DataTable
    Oracle 未能加载文件或程序集Oracle.DataAccess
    MySQL 各种主流 SQLServer 迁移到 MySQL 工具对比
    平衡树
    数据结构优化dp
  • 原文地址:https://www.cnblogs.com/keshuqi/p/6286323.html
Copyright © 2020-2023  润新知