• 【模板】二逼平衡树(树套树)


    题目描述

    您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:

    1. 查询k在区间内的排名

    2. 查询区间内排名为k的值

    3. 修改某一位值上的数值

    4. 查询k在区间内的前驱(前驱定义为严格小于x,且最大的数,若不存在输出-2147483647)

    5. 查询k在区间内的后继(后继定义为严格大于x,且最小的数,若不存在输出2147483647)

    注意上面两条要求和tyvj或者bzoj不一样,请注意

    输入输出格式

    输入格式:

    第一行两个数 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的后继

    输出格式:

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

    这就是树套树的模板题~

    我写的线段树套线段树~

    注意洛谷上是严格的前驱后继和bzoj上不同欧~

    附上代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    using namespace std;
    #define N 50010
    #define INF 2147483647
    int n,m,val[N];
    int L[N],R[N],K[N],P[N],V[N];
    int b[N<<1],tot,opt[N];
    int t[N<<2],siz[N*200],cnt,ls[N*200],rs[N*200],mx[N*200],mn[200*N];
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++)
    char buf[1000000],*p1,*p2;
    inline int rd()
    {
        register int x=0;register char c=nc();
        while(c<48)c=nc();
        while(c>47)x=((x+(x<<2))<<1)+(c^48),c=nc();
        return x;
    }
    inline void update(int p)
    {
        siz[p]=siz[ls[p]]+siz[rs[p]];
        mn[p]=min(mn[ls[p]],mn[rs[p]]);
        mx[p]=max(mx[ls[p]],mx[rs[p]]);
    }
    void Insert_intree(int l,int r,int &k,int place,int idx)
    {
        if(!k)
            k=++cnt;
        if(l==r)
        {
            siz[k]+=idx;
            if(siz[k])
                mn[k]=mx[k]=val[l];
            else 
                mn[k]=INF,mx[k]=-INF;
            return;
        }
        int mid=(l+r)>>1;
        if(mid>=place)
            Insert_intree(l,mid,ls[k],place,idx);
        else
            Insert_intree(mid+1,r,rs[k],place,idx);
        update(k);
        if(!siz[k])
            k=0;
    }
    void Insert_outtree(int l,int r,int k,int placeout,int placein,int idx)
    {
        Insert_intree(1,n,t[k],placein,idx);
        if(l==r)
            return;
        int mid=(l+r)>>1;
        if(mid>=placeout)
            Insert_outtree(l,mid,k<<1,placeout,placein,idx);
        if(mid<placeout)
            Insert_outtree(mid+1,r,k<<1|1,placeout,placein,idx);
    }
    int ask_intree_siz(int l,int r,int k,int x,int y)
    {
        if(x<=l&&r<=y)
            return siz[k];
        if(y<l||r<x||k==0)
            return 0;
        int mid=(l+r)>>1;
        return ask_intree_siz(l,mid,ls[k],x,y)+ask_intree_siz(mid+1,r,rs[k],x,y);
    }
    int ask_intree_min(int l,int r,int k,int x,int y)
    {
        if(x<=l&&r<=y) 
            return mn[k];
        if(y<l||r<x||k==0) 
            return INF;
        int mid=(l+r)>>1;
        return min(ask_intree_min(l,mid,ls[k],x,y),ask_intree_min(mid+1,r,rs[k],x,y)); 
    }
    int ask_intree_max(int l,int r,int k,int x,int y)
    {
        if(x<=l&&r<=y) 
            return mx[k];
        if(y<l||r<x||k==0) 
            return -INF;
        int mid=(l+r)>>1;
        return max(ask_intree_max(l,mid,ls[k],x,y),ask_intree_max(mid+1,r,rs[k],x,y)); 
    }
    int askrank(int l,int r,int k,int x,int y,int p)
    {
        if(l==r)
            return 1;
        int mid=(l+r)>>1,lson_siz=ask_intree_siz(1,n,t[k<<1],x,y);
        if(b[mid]>=p)
            return askrank(l,mid,k<<1,x,y,p);
        else
            return askrank(mid+1,r,k<<1|1,x,y,p)+lson_siz;  
    }
    int askval(int l,int r,int k,int x,int y,int p)
    {
        if(l==r)
            return b[l];
        int mid=(l+r)>>1,lson_siz=ask_intree_siz(1,n,t[k<<1],x,y);
        if(lson_siz>=p)
            return askval(l,mid,k<<1,x,y,p);
        else
            return askval(mid+1,r,k<<1|1,x,y,p-lson_siz);
    }
    int askpre(int l,int r,int k,int x,int y,int p)
    {
        if(l==r)
        {
            if(b[l]<p&&ask_intree_siz(1,n,t[k],x,y))
                return b[l];
            else
                return -INF;
        }
        int mid=(l+r)>>1,rmin=ask_intree_min(1,n,t[k<<1|1],x,y);
        if(p<=rmin)
            return askpre(l,mid,k<<1,x,y,p);
        else
            return askpre(mid+1,r,k<<1|1,x,y,p); 
    }
    int asknxt(int l,int r,int k,int x,int y,int p)
    {
        if(l==r)
        {
            if(b[l]>p&&ask_intree_siz(1,n,t[k],x,y))
                return b[l];
            else
                return INF;
        }
        int mid=(l+r)>>1,lmax=ask_intree_max(1,n,t[k<<1],x,y);
        if(p>=lmax)
            return asknxt(mid+1,r,k<<1|1,x,y,p);
        else
            return asknxt(l,mid,k<<1,x,y,p); 
    }
    int main()
    {
        n=rd();
        m=rd();
        for(int i=1;i<=n;i++)
        {
            val[i]=rd();
            b[++tot]=val[i];
        }
        for(int i=1;i<=m;i++)
        {
            opt[i]=rd();
            if(opt[i]!=3)
                L[i]=rd(),R[i]=rd(),K[i]=rd();
            else
            {
                P[i]=rd();
                V[i]=rd();
                b[++tot]=V[i];
            }
        }
        sort(b+1,b+tot+1);
        tot=unique(b+1,b+tot+1)-b-1;
        mn[0]=INF;
        mx[0]=-INF;
        for(int i=1;i<=n;i++)
        {
            int idx=lower_bound(b+1,b+tot+1,val[i])-b;
            Insert_outtree(1,tot,1,idx,i,1);
        }
        for(int i=1;i<=m;i++)
        {
            if(opt[i]==1)
                printf("%d
    ",askrank(1,tot,1,L[i],R[i],K[i]));
            if(opt[i]==2)
                printf("%d
    ",askval(1,tot,1,L[i],R[i],K[i]));
            if(opt[i]==3)
            {
                int idxx=lower_bound(b+1,b+tot+1,val[P[i]])-b;
                Insert_outtree(1,tot,1,idxx,P[i],-1);
                val[P[i]]=V[i];
                idxx=lower_bound(b+1,b+tot+1,val[P[i]])-b;
                Insert_outtree(1,tot,1,idxx,P[i],1);
            }
            if(opt[i]==4)
                printf("%d
    ",askpre(1,tot,1,L[i],R[i],K[i]));
            if(opt[i]==5)
                printf("%d
    ",asknxt(1,tot,1,L[i],R[i],K[i]));
        }
        return 0;
    }
  • 相关阅读:
    毕业设计过程复盘
    关于理想
    Python之网络模型与图形绘制工具networkx
    Python之Numpy:二元函数绘制/三维数据可视化/3D
    JavaScript之参数传递方式
    Python之滑动窗口
    [转] JavaScript 原型理解与创建对象应用
    [转] JavaScript 和事件
    [转] 三步将你的 React Native 项目运行在 Web 浏览器上面
    [转] Webpack 入门指迷
  • 原文地址:https://www.cnblogs.com/jiangminghong/p/10472733.html
Copyright © 2020-2023  润新知