zoukankan      html  css  js  c++  java
  • BZOJ 3065 带插入区间K小值

    http://www.lydsy.com/JudgeOnline/problem.php?id=3065

    思路:替罪羊树套权值线段树。

    当替罪羊树某个子树大于某个比利(比例)时就暴力重构,本题时间复杂度:O(nlog^3n)

    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<iostream>
    #include<vector>
    #define alpha 0.75
    #define N 10000005
    int read(){
        char ch=getchar();int t=0,f=1;
        while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
        while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
        return t*f;
    }
    int tmp;
    int n,m,sz,ans,root;
    int v[70005],dfn[70005],rt[70005],ls[70005],rs[70005];
    struct seg{int l,r,sum;}a[N];
    std::vector<int>p,t,rec;
    int newnode(){
        if (!rec.size()) return ++sz;
        else{
            int k=rec.back();rec.pop_back();
            return k;
        }
    }
    void recliam(int &x){
        if (!x) return;
        rec.push_back(x);
        recliam(a[x].l);recliam(a[x].r);
        a[x].sum=0;x=0;
    }
    void insert(int &k,int l,int r,int val,int f){
        if (!k) k=newnode();
        if (l==r){a[k].sum+=f;return;}
        int mid=(l+r)>>1;
        if (val<=mid) insert(a[k].l,l,mid,val,f);
        else insert(a[k].r,mid+1,r,val,f);
        a[k].sum=a[a[k].l].sum+a[a[k].r].sum;
        if (!a[k].sum) recliam(k);
    }
    void build(int &k,int l,int r){
        int mid=(l+r)>>1;
        if (l>r) return;
        if (l==r){
            k=dfn[l];insert(rt[k],0,70000,v[k],1);return;
        }
        k=dfn[mid];
        build(ls[k],l,mid-1);build(rs[k],mid+1,r);
        for (int i=l;i<=r;i++)
         insert(rt[k],0,70000,v[dfn[i]],1);
    }
    void del(int &x){
        if (!x) return;recliam(rt[x]);
        del(ls[x]);p.push_back(x);del(rs[x]);
        x=0;
    }
    void rebuild(int &x){
        del(x);int s1=p.size();
        for (int i=1;i<=s1;i++) dfn[i]=p[i-1];
        build(x,1,s1);
        p.clear();
    }
    int modify(int k,int x,int val){
        insert(rt[k],0,70000,val,1);
        int t,L=a[rt[ls[k]]].sum;
        if (L+1==x){t=v[k];v[k]=val;}
        else if (L>=x) t=modify(ls[k],x,val);
        else t=modify(rs[k],x-L-1,val);
        insert(rt[k],0,70000,t,-1);
        return t;
    }
    void query(int k,int l,int r){
        int L=a[rt[ls[k]]].sum,R=a[rt[k]].sum;
        if (l==1&&r==R){t.push_back(rt[k]);return;}
        if (l<=L+1&&r>=L+1)p.push_back(v[k]);
        if (r<=L)query(ls[k],l,r);
        else if (l>L+1) query(rs[k],l-L-1,r-L-1);
        else{
            if (l<=L) query(ls[k],l,L);
            if (R>L+1) query(rs[k],1,r-L-1);
        }
    }
    int solve_query(int L,int R,int K){
        query(root,L,R);K--;
        int l=0,r=70000,s1=t.size(),s2=p.size();
        while (l<r){
            int mid=(l+r)>>1,sum=0;
            for (int i=0;i<s1;i++) sum+=a[a[t[i]].l].sum;
            for (int i=0;i<s2;i++)
             if (p[i]>=l&&p[i]<=mid) sum++;
            if (K<sum){
                for (int i=0;i<s1;i++) t[i]=a[t[i]].l;
                r=mid;
            } else{
                for (int i=0;i<s1;i++) t[i]=a[t[i]].r;
                l=mid+1;K-=sum;
            }
        }
        t.clear();p.clear();
        return l;
    }
    void insert(int &k,int x,int val){
        if (!k){
            k=++n;
            insert(rt[k],0,70000,val,1);
            v[k]=val;
            return;
        }
        insert(rt[k],0,70000,val,1);
        int L=a[rt[ls[k]]].sum;
        if (L>=x) insert(ls[k],x,val);else insert(rs[k],x-L-1,val);
        if (a[rt[k]].sum*alpha>std::max((double)a[rt[ls[k]]].sum,(double)a[rt[rs[k]]].sum)){
            if (tmp){
                if (ls[k]==tmp) rebuild(ls[k]);
                else rebuild(rs[k]);
                tmp=0; 
            }
        }else tmp=k;    
    }
    int main(){
        n=read();
        for (int i=1;i<=n;i++) v[i]=read();
        for (int i=1;i<=n;i++) dfn[i]=i;
        build(root,1,n);
        m=read();
        char ch[2];int x,y,K;
        while (m--){
            scanf("%s",ch);
            x=read();y=read();x^=ans;y^=ans;
            switch(ch[0]){
                case 'Q':K=read();K^=ans;ans=solve_query(x,y,K);printf("%d
    ",ans);break;
                case 'M':modify(root,x,y);break;
                case 'I':tmp=0;insert(root,x-1,y);if (tmp){tmp=0;rebuild(root);}break;
            }
        }
    }
  • 相关阅读:
    查看mysql数据库引擎
    crontab 从nano 转换为 vim
    Linux中,去掉终端显示的当前目录的绝对路径
    nginx 卸载后重新安装/etc/nginx配置文件没了,cannot open /etc/nginx/nginx.conf (No such file or directory)
    rabbitmq 配置
    OSError: mysql_config not found
    No module named 'ConfigParser'
    windows 安装tensorflow
    微服务架构设计
    centOS rabbitmq 安装
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5693207.html
Copyright © 2011-2022 走看看