zoukankan      html  css  js  c++  java
  • BZOJ1901(主席树+树状数组 实现“动态主席树”)


    BZOJ1901: Zju2112 Dynamic Rankings##

      Time Limit: 10 Sec
      Memory Limit: 128 MB

    Description###

       给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改变后的a继续回答上面的问题。
     

    Input###

       第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。分别表示序列的长度和指令的个数。
      第二行有n个数,表示a[1],a[2]……a[n],这些数都小于10^9。
      接下来的m行描述每条指令
      每行的格式是下面两种格式中的一种。
      Q i j k 或者 C i t
      Q i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)
      表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。
      C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t
      m,n≤10000
     

    Output###

       对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。
     

    Sample Input###

       5 3
       3 2 1 4 7
       Q 1 4 3
       C 2 6
       Q 2 5 3
     

    Sample Output###

      3
      6
        

    HINT

    题目地址:BZOJ1901: Zju2112 Dynamic Rankings

    题目大意: 题目很简洁了:)

    题解:

      对于不修改的情况
      我们对每一个数都开一颗主席树(这里第i颗主席树记录前i个数的情况)
      只要对目标区间的左右端点的主席树差分下就能求出 (kth)
      如何支持动态
      想到树状数组可以 (logN) 支持前缀和
      我们只要像树状数组一样开主席树就可以了
      例如第 (c[8]) 颗主席树记录的是 (c[4])颗和(c[6])颗和(c[7])颗和第 (8) 个数的情况
    p1
      对于每次修改只要修改 (logN)颗主席树,修改每个主席树上 (logN)个点
      然后 orz hzw


    AC代码

    #include <cstdio> 
    #include <algorithm>
    using namespace std;
    const int N=1e4+5,M=2200001;
    int n,m,tot,Lnum,Rnum;
    int val[N],K[N],hash[N<<1],A[N],B[N];
    char op[N];
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int sz,sum[M],son[M][2],root[N];
    void change(int u,int &v,int l,int r,int k,int x){
        v=++sz;
        sum[v]=sum[u]+x;
        son[v][0]=son[u][0];
        son[v][1]=son[u][1];
        if(l==r)return;
        int mid=(l+r)>>1;
        if(k<=mid)change(son[u][0],son[v][0],l,mid,k,x);
        else change(son[u][1],son[v][1],mid+1,r,k,x);
    }
    int L[30],R[30];
    int query(int l,int r,int k){
        if(l==r)return l;
        int suml=0,sumr=0;
        for(int i=1;i<=Lnum;i++)suml+=sum[son[L[i]][0]];
        for(int i=1;i<=Rnum;i++)sumr+=sum[son[R[i]][0]];
        int mid=(l+r)>>1;
        if(sumr-suml>=k){
            for(int i=1;i<=Lnum;i++)L[i]=son[L[i]][0];
            for(int i=1;i<=Rnum;i++)R[i]=son[R[i]][0];
            return query(l,mid,k);
        }else{
            for(int i=1;i<=Lnum;i++)L[i]=son[L[i]][1];
            for(int i=1;i<=Rnum;i++)R[i]=son[R[i]][1];
            return query(mid+1,r,k-(sumr-suml));
        }
    }
    int main(){
        n=read(),m=read();
        for(int i=1;i<=n;i++)
            val[i]=hash[++tot]=read();
        for(int i=1;i<=m;i++){
            scanf("
    ");
            op[i]=getchar();
            A[i]=read(),B[i]=read();
            if(op[i]=='Q')K[i]=read();
            else hash[++tot]=B[i];
        }
        sort(hash+1,hash+tot+1);
        int New=unique(hash+1,hash+tot+1)-hash-1;
        for(int i=1;i<=n;i++){
            int k=lower_bound(hash+1,hash+New+1,val[i])-hash;
            for(int j=i;j<=n;j+=j&(-j))
                change(root[j],root[j],1,New,k,1);
        }
        for(int i=1;i<=m;i++)
            if(op[i]=='Q'){
                Lnum=0,Rnum=0;A[i]--;
                for(int j=A[i];j>0;j-=j&(-j))
                    L[++Lnum]=root[j];
                for(int j=B[i];j>0;j-=j&(-j))
                    R[++Rnum]=root[j];
                printf("%d
    ",hash[query(1,New,K[i])]);
            }else{
                int k;
                k=lower_bound(hash+1,hash+New+1,val[A[i]])-hash;
                for(int j=A[i];j<=n;j+=j&(-j))
                    change(root[j],root[j],1,New,k,-1);
                val[A[i]]=B[i];
                k=lower_bound(hash+1,hash+New+1,B[i])-hash;
                for(int j=A[i];j<=n;j+=j&(-j))
                    change(root[j],root[j],1,New,k,1);
            }
        return 0;
    }
    


      作者:skl_win
      出处:https://www.cnblogs.com/shaokele/
      本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    C# Dictionary几种遍历方式
    Android 代码中文字在手机上显示乱码问题解决方法
    【Android学习5】Clean 之后R文件丢失
    【android学习4】Eclipse中Clean作用
    Java基础语法(练习)
    Java基础语法(自定义类、ArrayList集合)
    Java基础语法(方法)
    Java基础语法(数组)
    Java基础(Scanner、Random、流程控制语句)
    Java基础(变量、运算符)
  • 原文地址:https://www.cnblogs.com/shaokele/p/9741018.html
Copyright © 2011-2022 走看看