• [BZOJ 1901]Dynamic Rankings


    [BZOJ 1901]Dynamic Rankings

    题目

    给定一个含有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

    OUTPUT

    3

    6

    解题报告

    打了一下午的静态主席树,终于进阶到动态的了= =

    树状数组套一个主席树

    我们想,主席树是通过前缀和来维护信息的,我们一修改就全都乱了,所以我们需要一个数据结构来维护前缀和,很自然的就想到了树状数组

    我们在修改时,利用树状数组,将其原来所产生的影响清除,然后进行更新,就可以对主席树进行动态操作了

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdio>
      5 using namespace std;
      6 inline int read(){
      7     int sum(0);
      8     char ch(getchar());
      9     for(;ch<'0'||ch>'9';ch=getchar());
     10     for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar());
     11     return sum;
     12 }
     13 int n,m;
     14 int tot,size,cnt;
     15 int v[10005],num[20005],has[20005];
     16 int rt[10005],sum[2500005],lch[2500005],rch[2500005];
     17 int A[10005],B[10005],K[10005];
     18 bool flag[10005];
     19 int a,b,L[30],R[30];
     20 char op[2];
     21 inline int lowbit(int x){
     22     return x&-x;
     23 }
     24 inline int find(int x){
     25     int l(1),r(size),mid;
     26     while(l<=r){
     27         mid=(l+r)>>1;
     28         if(has[mid]<x)
     29             l=mid+1;
     30         else
     31             r=mid-1;
     32     }
     33     return l;
     34     //return lower_bound(has+1,has+size+1,x)-has;
     35 }
     36 inline void update(int &x,int las,int pos,int w,int l,int r){
     37     x=++cnt;
     38     lch[x]=lch[las];
     39     rch[x]=rch[las];
     40     sum[x]=sum[las]+w;
     41     if(l==r)
     42         return;
     43     int mid((l+r)>>1);
     44     if(pos<=mid)
     45         update(lch[x],lch[las],pos,w,l,mid);
     46     else
     47         update(rch[x],rch[las],pos,w,mid+1,r);
     48 }
     49 inline int query(int l,int r,int k){
     50     if(l==r)
     51         return l;
     52     int suml(0),sumr(0),mid((l+r)>>1);
     53     for(int i=1;i<=a;++i)suml+=sum[lch[L[i]]];
     54     for(int i=1;i<=b;++i)sumr+=sum[lch[R[i]]];
     55     if(sumr-suml>=k){
     56         for(int i=1;i<=a;++i)L[i]=lch[L[i]];
     57         for(int i=1;i<=b;++i)R[i]=lch[R[i]];
     58         return query(l,mid,k);
     59     }
     60     else{
     61         for(int i=1;i<=a;++i)L[i]=rch[L[i]];
     62         for(int i=1;i<=b;++i)R[i]=rch[R[i]];
     63         return query(mid+1,r,k-(sumr-suml));
     64     }
     65 }
     66 int main(){
     67     n=read(),m=read();
     68     for(int i=1;i<=n;++i){
     69         v[i]=read();
     70         num[++tot]=v[i];
     71     }
     72     for(int i=1;i<=m;++i){
     73         scanf("%s",op);
     74         if(op[0]=='Q'){
     75             flag[i]=1;
     76             A[i]=read();
     77             B[i]=read();
     78             K[i]=read();
     79         }
     80         else{
     81             A[i]=read();
     82             B[i]=read();
     83             num[++tot]=B[i];
     84         }
     85     }
     86     sort(num+1,num+tot+1);
     87     has[++size]=num[1];
     88     for(int i=2;i<=tot;++i)
     89         if(num[i]!=num[i-1])
     90             has[++size]=num[i];
     91     for(int i=1;i<=n;++i){
     92         int tmp(find(v[i]));
     93         for(int j=i;j<=n;j+=lowbit(j))
     94             update(rt[j],rt[j],tmp,1,1,size);
     95     }
     96     for(int i=1;i<=m;++i){
     97         if(flag[i]){
     98             a=b=0;
     99             --A[i];
    100             for(int j=A[i];j>0;j-=lowbit(j))
    101                 L[++a]=rt[j];
    102             for(int j=B[i];j>0;j-=lowbit(j))
    103                 R[++b]=rt[j];
    104             printf("%d
    ",has[query(1,size,K[i])]);
    105         }
    106         else{
    107             int tmp(find(v[A[i]]));
    108             for(int j=A[i];j<=n;j+=lowbit(j))
    109                 update(rt[j],rt[j],tmp,-1,1,size);
    110             v[A[i]]=B[i];
    111             tmp=find(B[i]);
    112             for(int j=A[i];j<=n;j+=lowbit(j))
    113                 update(rt[j],rt[j],tmp,1,1,size);
    114         }
    115     }
    116 }
    View Code
  • 相关阅读:
    51nod1693 水群
    51nod 1158 全是1的最大子矩阵
    poj1192 最优连通子集(树形dp)
    51nod 1051 最大子矩阵和(dp)
    codeforces723 D. Lakes in Berland(并查集)
    51nod 1065 最小正子段和
    poj1122 FDNY to the Rescue!(dij+反向建图+输出路径)
    51nod 1050 循环数组最大子段和
    hdu4781 Assignment For Princess(构造)
    51nod 1043 幸运号码(数位dp)
  • 原文地址:https://www.cnblogs.com/hzoi-mafia/p/7582527.html
Copyright © 2020-2023  润新知