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


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

    前置芝士 P3369 【模板】普通平衡树

    线段树套平衡树

    这里写的是线段树+splay(不吸氧竟然卡过了)

    对线段树的每个节点都维护一颗平衡树

    每次把给定区间内

    线段树上节点维护的平衡树的信息

    查询一遍就好辣

    $opt2$:每次二分一个答案k,蓝后用$opt1$跑,再判断偏大还是偏小

    我真的要好好背背splay的各种神仙操作了TAT

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    inline int Max(int a,int b){return a>b?a:b;}
    inline int Min(int a,int b){return a<b?a:b;}
    void read(int &x){
        static char c=getchar();x=0;
        while(c<'0'||c>'9') c=getchar();
        while('0'<=c&&c<='9') x=x*10+(c^48),c=getchar();
    }
    #define N 50005
    const int inf=2147483647;
    struct node{
        int ch[2],siz,v,fa;
        void clear(){ch[0]=ch[1]=v=fa=siz=0;}
    }a[4000005];
    int n,m,u,A[N];
    queue <int> lit;
    int New(){
        if(lit.empty()) return ++u;
        int p=lit.front(); lit.pop(); return p;
    }
    struct Splay{
        #define lc a[x].ch[0]
        #define rc a[x].ch[1]
        int rt,re;
        inline void up(int x){a[x].siz=a[lc].siz+a[rc].siz+1;}
        inline int whi(int y,int x){return a[y].ch[1]==x;}
        void turn(int x,int &k){
            int y=a[x].fa,z=a[y].fa,l=whi(y,x),r=l^1;
            if(y==k) k=x;
            else a[z].ch[whi(z,y)]=x;
            a[a[x].ch[r]].fa=y; a[y].fa=x; a[x].fa=z;
            a[y].ch[l]=a[x].ch[r]; a[x].ch[r]=y;
            up(y); up(x);
        }
        void splay(int x,int &k){
            for(;x!=k;turn(x,k)){
                int y=a[x].fa,z=a[y].fa;
                if(y!=k) turn((whi(z,y)^whi(y,x))?x:y,k);
            }
        }
        int find(int x,int k){
            while(a[lc].siz+1!=k){
                if(a[lc].siz+1>=k) x=lc;
                else k=k-a[lc].siz-1,x=rc;
            }return x;
        }
        int torank(int k){
            int x=rt,re=0,id=0;
            while(x){
                if(a[x].v==k) id=x;
                if(a[x].v>=k) x=lc;
                else re+=a[lc].siz+1,x=rc;
            }if(id) splay(id,rt);//
            return re;
        }
        void ins(int k){
            int x=rt,Fa=0;
            while(x) Fa=x,x=a[x].ch[a[x].v<=k];
            x=New(); a[x].v=k,a[x].fa=Fa;
            if(rt) a[Fa].ch[a[Fa].v<=k]=x,splay(x,rt);
            else rt=x;
        }
        void del(int k){
            int x=rt,p,tmp;
            while(a[x].v!=k) x=a[x].ch[a[x].v<=k];
            splay(x,rt); tmp=rt;
            if(lc&&rc){//
                p=find(rt,a[lc].siz); splay(p,lc),x=rt;
                a[lc].ch[1]=rc,a[rc].fa=lc;
                rt=lc,a[rt].fa=0,up(rt);
            }else if(lc) a[lc].fa=0,rt=lc;
            else if(rc) a[rc].fa=0,rt=rc;
            else rt=0;
            a[tmp].clear(); lit.push(tmp);
        }
        void Pre(int x,int k){
            if(!x) return;
            if(re<a[x].v&&a[x].v<k) re=a[x].v;
            Pre(a[x].ch[a[x].v<k],k);
        }
        void Last(int x,int k){
            if(!x) return ;
            if(k<a[x].v&&a[x].v<re) re=a[x].v;
            Last(a[x].ch[a[x].v<=k],k);
        }
        int pre(int k){re=-inf;Pre(rt,k);return re;}
        int last(int k){re=inf;Last(rt,k);return re;}
        #undef lc
        #undef rc
    }s[N<<2];
    struct Seg_tree{
        #define lc o<<1
        #define rc o<<1|1
        #define mid (l+r)/2
        void Ins(int o,int l,int r,int x,int v){
            s[o].ins(v);
            if(l==r) return ;
            if(x<=mid) Ins(lc,l,mid,x,v);
            else Ins(rc,mid+1,r,x,v);
        }
        int Ask1(int o,int l,int r,int x1,int x2,int v){
            if(x1<=l&&r<=x2) return s[o].torank(v);
            int re=0;
            if(x1<=mid) re+=Ask1(lc,l,mid,x1,x2,v);
            if(x2>mid) re+=Ask1(rc,mid+1,r,x1,x2,v);
            return re;
        }
        void Modi(int o,int l,int r,int x,int v1,int v2){
            s[o].del(v1); s[o].ins(v2);
            if(l==r) return ;
            if(x<=mid) Modi(lc,l,mid,x,v1,v2);
            else Modi(rc,mid+1,r,x,v1,v2);
        }
        int Ask4(int o,int l,int r,int x1,int x2,int v){
            if(x1<=l&&r<=x2) return s[o].pre(v);
            int re=-inf;
            if(x1<=mid) re=Max(re,Ask4(lc,l,mid,x1,x2,v));
            if(x2>mid) re=Max(re,Ask4(rc,mid+1,r,x1,x2,v));
            return re;
        }
        int Ask5(int o,int l,int r,int x1,int x2,int v){
            if(x1<=l&&r<=x2) return s[o].last(v);
            int re=inf;
            if(x1<=mid) re=Min(re,Ask5(lc,l,mid,x1,x2,v));
            if(x2>mid) re=Min(re,Ask5(rc,mid+1,r,x1,x2,v));
            return re;
        }
        #undef lc
        #undef rc
        #undef mid
    }T;
    int main(){
        read(n);read(m); register int i; int q1,q2,q3,q4;
        for(i=1;i<=n;++i) read(A[i]),T.Ins(1,1,n,i,A[i]);
        while(m--){
            read(q1);read(q2);read(q3);
            switch(q1){
                case 1:{read(q4),printf("%d
    ",T.Ask1(1,1,n,q2,q3,q4)+1);break;}//排名要+1,算上自己
                case 2:{
                    read(q4);
                    int l=0,r=1e8;
                    while(l<r){ //二分比较特殊,每次二分的mid要偏大一点
                        int mid=(l+r+1)/2;
                        if(T.Ask1(1,1,n,q2,q3,mid)<q4) l=mid;
                        else r=mid-1;
                    }printf("%d
    ",l);
                    break;
                }
                case 3:{T.Modi(1,1,n,q2,A[q2],q3),A[q2]=q3;break;}
                case 4:{read(q4),printf("%d
    ",T.Ask4(1,1,n,q2,q3,q4));break;}
                case 5:{read(q4),printf("%d
    ",T.Ask5(1,1,n,q2,q3,q4));break;}
            }
        }return 0;
    }
  • 相关阅读:
    xtu summer individual 6 B
    Docker和宿主机操作系统文件目录互相隔离的实现原理
    SAP成都研究院飞机哥: SAP C4C中国本地化之微信聊天机器人的集成
    C4C销售订单行项目价格维护方法
    Jerry Wang诚邀广大SAP同仁免费加入我的知识星球,共同探讨SAP技术问题
    为什么CRM Opportunity的删除会触发一个通向BW系统的RFC
    如何用代码填充S/4HANA销售订单行项目的数量字段
    SAP成都研究院大卫哥:SAP C4C中国本地化之微信小程序集成
    如何获得C4C里某个code字段对应的描述信息
    如何用代码的方式取出SAP C4C销售订单创建后所有业务伙伴的数据
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/10590535.html
Copyright © 2020-2023  润新知