zoukankan      html  css  js  c++  java
  • [学习笔记]树套树 线段树套Splay

    今天调了一个早上哈哈哈,不过因为(Splay),常数比较大

    洛谷的评测记录:

    (Code Below:)

    #include <bits/stdc++.h>
    #define ll long long
    #define mid (l+r>>1)
    using namespace std;
    const int maxn=4000010;
    const int inf=2147483647;
    int n,m,sz,ans,Max;
    int a[maxn],ch[maxn][2],fa[maxn],siz[maxn],cnt[maxn],key[maxn],rt[maxn];
    
    inline void splayclear(int x){
        fa[x]=ch[x][0]=ch[x][1]=siz[x]=cnt[x]=key[x]=0;
    }
    inline bool get(int x){
        return ch[fa[x]][1]==x;
    }
    inline void update(int x){
        siz[x]=(ch[x][0]?siz[ch[x][0]]:0)+(ch[x][1]?siz[ch[x][1]]:0)+cnt[x];
    }
    inline void rotate(int x){
        int y=fa[x],z=fa[y],k=get(x);
        ch[y][k]=ch[x][k^1];fa[ch[y][k]]=y;
        ch[x][k^1]=y;fa[y]=x;fa[x]=z;
        if(z) ch[z][ch[z][1]==y]=x;
        update(y);update(x);
    }
    inline void splay(int i,int x,int top){
        for(int y,z;fa[x]!=top;rotate(x)){
            y=fa[x],z=fa[y];
            if(z!=top) rotate(get(x)==get(y)?y:x);
        }
        if(!top) rt[i]=x;
    }
    inline void splayinsert(int i,int val){
        int x=rt[i],y;
        if(!rt[i]){
            rt[i]=x=++sz;fa[x]=ch[x][0]=ch[x][1]=0;
            key[x]=val;siz[x]=cnt[x]=1;return;
        }
        while(1){
            if(key[x]==val){cnt[x]++;update(y);break;}
            y=x;x=ch[x][key[x]<val];
            if(x==0){
                x=++sz;key[x]=val;siz[x]=cnt[x]=1;
                ch[y][key[y]<val]=x;fa[x]=y;
                update(y);break;
            }
        }
        splay(i,x,0);
    }
    inline int splayrank(int i,int val){
        int x=rt[i],ret=0;
        while(x>0){
            if(val<key[x]) x=ch[x][0];
            else {
                ret+=(ch[x][0]?siz[ch[x][0]]:0);
                if(val==key[x]) return ret;
                ret+=cnt[x];x=ch[x][1];
            }
        }
        return ret;
    }
    inline int splayfind(int i,int val){
        int x=rt[i];
        while(x>0){
            if(val==key[x]){splay(i,x,0);return x;}
            x=ch[x][key[x]<val];
        }
    }
    inline int splaypre(int i){int x=ch[rt[i]][0];while(ch[x][1])x=ch[x][1];return x;}
    inline int splaysuc(int i){int x=ch[rt[i]][1];while(ch[x][0])x=ch[x][0];return x;}
    inline void splaydel(int i,int val){
        int x=splayfind(i,val),y=rt[i];
        if(cnt[x]>1){cnt[x]--;update(x);return;}
        if(!ch[x][0]&&!ch[x][1]){splayclear(rt[i]);rt[i]=0;return;}
        if(!ch[x][0]){y=ch[x][1];rt[i]=y;fa[y]=0;return;}
        if(!ch[x][1]){y=ch[x][0];rt[i]=y;fa[y]=0;return;}
        splay(i,splaypre(i),0);
        ch[rt[i]][1]=ch[y][1];fa[ch[y][1]]=rt[i];
        splayclear(y);update(rt[i]);
    }
    inline int splaygetpre(int i,int val){
        int x=rt[i];
        while(x>0){
            if(val<=key[x]) x=ch[x][0];
            else {
                if(key[x]>ans) ans=key[x];
                x=ch[x][1];
            }
        }
        return ans;
    }
    inline int splaygetsuc(int i,int val){
        int x=rt[i];
        while(x>0){
            if(val>=key[x]) x=ch[x][1];
            else {
                if(key[x]<ans) ans=key[x];
                x=ch[x][0];
            }
        }
        return ans;
    }
    
    inline void seginsert(int l,int r,int rt,int x,int val){
        splayinsert(rt,val);
        if(l == r) return;
        if(x <= mid) seginsert(l,mid,rt<<1,x,val);
        else seginsert(mid+1,r,rt<<1|1,x,val);
    }
    inline void segrank(int L,int R,int val,int l,int r,int rt){
        if(L <= l && r <= R){ans+=splayrank(rt,val);return;}
        if(L <= mid) segrank(L,R,val,l,mid,rt<<1);
        if(R > mid) segrank(L,R,val,mid+1,r,rt<<1|1);
    }
    inline void segchange(int l,int r,int rt,int x,int val){
        splaydel(rt,a[x]);splayinsert(rt,val);
        if(l == r){a[x]=val;return;}
        if(x <= mid) segchange(l,mid,rt<<1,x,val);
        else segchange(mid+1,r,rt<<1|1,x,val);
    }
    inline void segpre(int L,int R,int val,int l,int r,int rt){
        if(L <= l && r <= R){ans=max(ans,splaygetpre(rt,val));return;}
        if(L <= mid) segpre(L,R,val,l,mid,rt<<1);
        if(R > mid) segpre(L,R,val,mid+1,r,rt<<1|1);
    }
    inline void segsuc(int L,int R,int val,int l,int r,int rt){
        if(L <= l && r <= R){ans=min(ans,splaygetsuc(rt,val));return;}
        if(L <= mid) segsuc(L,R,val,l,mid,rt<<1);
        if(R > mid) segsuc(L,R,val,mid+1,r,rt<<1|1);
    }
    inline int getkth(int L,int R,int k){
        int l=0,r=Max+1,Mid;
        while(l<r){
            Mid=l+r>>1;ans=0;
            segrank(L,R,Mid,1,n,1);
            if(ans<k) l=Mid+1;
            else r=Mid;
        }
        return l-1;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            seginsert(1,n,1,i,a[i]);
            Max=max(Max,a[i]);
        }
        int opt,l,r,val;
        while(m--){
            scanf("%d%d%d",&opt,&l,&r);
            switch(opt){
                case 1:scanf("%d",&val);ans=0;segrank(l,r,val,1,n,1);printf("%d
    ",ans+1);break;
                case 2:scanf("%d",&val);printf("%d
    ",getkth(l,r,val));break;
                case 3:segchange(1,n,1,l,r);break;
                case 4:scanf("%d",&val);ans=-inf;segpre(l,r,val,1,n,1);printf("%d
    ",ans);break;
                case 5:scanf("%d",&val);ans=inf;segsuc(l,r,val,1,n,1);printf("%d
    ",ans);break;
            }
        }
        return 0;	
    }
    
  • 相关阅读:
    c++之输出文件和输入文件的处理
    C++之输入输出流
    c++之虚析构函数
    c++之虚函数和基类指针
    接口自动化测试框架Karate入门
    uiautomator+cucumber实现移动app自动化测试
    calabash-android Win10 入门笔记
    Page Object 模式编写UiAutomator脚本
    ruby脚本打印日志到rspec的报告文件中
    Ruby跳出多层循环 catch...throw
  • 原文地址:https://www.cnblogs.com/owencodeisking/p/9724522.html
Copyright © 2011-2022 走看看