码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-10-22 20:34:24      阅读:116      评论:0      收藏:0      [点我收藏+]

标签:--   EAP   and   返回   lin   div   ons   真心   mem   

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

真是超级好玩

其实说白了,就是对于线段树每一个节点维护一个平衡树

STL依赖症,不能用,只得手写平衡树,真心累

学校里花了两节课,码完了238行,回家以后把操作二重复情况判断以后,一遍AC

这种题,就是:说起来好做,做起来......

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=100005;
const int MAXN=100005;
int n,m;
int a[MAXN];
struct Treap{
    struct node{//结构体重建树
        int l;//左儿子
        int r;//右儿子
        int k;//权值
        int p;//优先级
        int c;//重复元素个数
        int s;//子节点个数
        #define l(x) t[x].l
        #define r(x) t[x].r
        #define v(x) t[x].k
        #define p(x) t[x].p
        #define c(x) t[x].c
        #define s(x) t[x].s
    }t[N*20];
    int cnty;
    int pooly;
    int n;
    int data;
    Treap(){pooly=0;cnty=0;}
    inline void upt(const int &k){//传递 
        s(k)=s(l(k))+s(r(k))+c(k);
    }
    inline void zig(int &k){//左旋 
        int y=l(k);
        l(k)=r(y);
        r(y)=k;
        s(y)=s(k);
        upt(k);
        k=y;
    }
    inline void zag(int &k){//右旋 
        int y=r(k);
        r(k)=l(y);
        l(y)=k;
        s(y)=s(k);
        upt(k);
        k=y;
    }
    inline void ins(int &k,const int &val){//插入节点 
        if(!k){//新建一个节点
            k=++pooly; 
            v(k)=val;
            p(k)=rand();//赋值一个随机的优先级 
            c(k)=s(k)=1;
            l(k)=r(k)=0;//没有左右儿子 
            return;
        }
        else ++s(k);
        if(v(k)==val) ++c(k);//有重复元素
        else if(val<v(k)){
            ins(l(k),val);
            if(p(l(k))<p(k)) zig(k);//左旋:维护堆性质 
        } 
        else{
            ins(r(k),val);
            if(p(r(k))<p(k)) zag(k);//右旋:维护堆性质 
        }    
    }
    int Rk(int root,const int &val){
        int x=root;
        int res=0;
        while(x){
            if(val==v(x)) return res+s(l(x))+1;//找到了:返回排名 
            if(val<v(x)) x=l(x);
            else res+=s(l(x))+c(x),x=r(x); 
        }
    }
    inline int serch_min(int root,const int &val){
        int x=root,res=-2147483647;
        while(x){
            if(v(x)<val) res=v(x),x=r(x);
            else x=l(x); 
        }
        return res;
    }
    inline int serch_max(int root,const int &val){
        int x=root,res=2147483647;
        while(x){
            if(v(x)>val) res=v(x),x=l(x);
            else x=r(x); 
        }
        return res;    
    }
    inline int serch(int root,const int &val){
        int x=root,res=0;
        while(x){
            if(v(x)<val){
                res+=c(x)+s(l(x));
                x=r(x);
            }
            else{
                x=l(x);
            }
        }
        return res;
    }
    inline int Kth(int root,int k){
        int x=root;
        while(x){
            if(s(l(x))<k&&s(l(x))+c(x)>=k) return v(x);
            if(s(l(x))>=k) x=l(x);
            else k-=s(l(x))+c(x),x=r(x);
        }
        return 0;
    }
    inline void del(int &k,const int &val){
        if(v(k)==val){
            if(c(k)>1) --c(k),--s(k);
            else if(!l(k)||!r(k)) k=l(k)+r(k);
            else if(p(l(k))<p(r(k))) zig(k),del(k,val);
            else zag(k),del(k,val);
            return;
        }
        --s(k);
        if(val<v(k)) del(l(k),val);
        else del(r(k),val);
        return;
    } 
}TP; 
struct Sugment_Tree{
    #define il inline
    #define mid (l+r)/2
    int root[N*8];
    int ans;
    Sugment_Tree(){memset(root,0,sizeof(root));ans=0;}
    il void ins(int l,int r,int num,int pos,int val){
        if(l>pos||r<pos) return;
        if(l==r&&r==pos){
            TP.ins(root[num],val);
            return;
        }
        TP.ins(root[num],val);
        ins(l,mid,num<<1,pos,val);
        ins(mid+1,r,num<<1|1,pos,val);
    }
    il void del(int l,int r,int num,int pos,int val){
        if(l>pos||r<pos) return;
        if(l==r&&r==pos){
            TP.del(root[num],val);
            return;
        }
        TP.del(root[num],val);
        del(l,mid,num<<1,pos,val);
        del(mid+1,r,num<<1|1,pos,val);
    }
    il int ranking(int l,int r,int num,int L,int R,int val){
        if(l>R||r<L) return 0;
        if(l>=L&&r<=R){
            if(TP.serch_min(root[num],val)==-2147483647) return 0;
            return TP.serch(root[num],val);
        }
        return ranking(l,mid,num<<1,L,R,val)+ranking(mid+1,r,num<<1|1,L,R,val);
    }
    il int rpk(int l,int r,int num,int L,int R,int val){
        return ranking(l,r,num,L,R,val)+1;
    }
    il int ask(int L,int R,int val){
        int l=0,r=100000000,ans;
        while(l<=r){
            if(rpk(1,n,1,L,R,mid)<=val) ans=mid,l=mid+1;
            else r=mid-1;
        }
        return ans;
    }
    il void pre(int l,int r,int num,int L,int R,int val){
        if(l>R||r<L) return;
        if(l>=L&&r<=R){
            ans=max(ans,TP.serch_min(root[num],val));
            return;
        }
        pre(l,mid,num<<1,L,R,val);
        pre(mid+1,r,num<<1|1,L,R,val);
    }
    il int pre_ask(int L,int R,int val){
        ans=-2147483647;
        pre(1,n,1,L,R,val);
        return ans;
    }
    il void suf(int l,int r,int num,int L,int R,int val){
        if(l>R||r<L) return;
        if(l>=L&&r<=R){
            ans=min(ans,TP.serch_max(root[num],val));
            return;
        }
        suf(l,mid,num<<1,L,R,val);
        suf(mid+1,r,num<<1|1,L,R,val);
    }
    il int suf_ask(int L,int R,int val){
        ans=2147483647;
        suf(1,n,1,L,R,val);
        return ans;
    }
}T;
int main(){
    srand((unsigned)time(NULL));
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),T.ins(1,n,1,i,a[i]);
    //cout<<T.ranking(1,n,1,1,3,3)<<endl;
    while(m--){
        int opt;
        scanf("%d",&opt);
        int l,r,val,pos;
        if(opt==1) {
            scanf("%d%d%d",&l,&r,&val);
            int p=T.rpk(1,n,1,l,r,val);
            printf("%d\n",p);
        }
        else if(opt==2){
            scanf("%d%d%d",&l,&r,&val);
            int p=T.ask(l,r,val);
            printf("%d\n",p);
        }
        else if(opt==3){
            scanf("%d%d",&pos,&val);
            T.del(1,n,1,pos,a[pos]);
            a[pos]=val;
            T.ins(1,n,1,pos,a[pos]);
        }
        else if(opt==4){
            scanf("%d%d%d",&l,&r,&val);
            int p=T.pre_ask(l,r,val);
            printf("%d\n",p);
        }
        else{
            scanf("%d%d%d",&l,&r,&val);
            int p=T.suf_ask(l,r,val);
            printf("%d\n",p);
        }
    }
    return 0;
}

 

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

标签:--   EAP   and   返回   lin   div   ons   真心   mem   

原文地址:https://www.cnblogs.com/QYJ060604/p/11722099.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!