• 【BOZJ 1901】Zju2112 Dynamic Rankings


    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继续回答上面的问题。你需要编一个这样的程序,从输入文件中读入序列a,然后读入一系列的指令,包括询问指令和修改指令。对于每一个询问指令,你必须输出正确的回答。 第一行有两个正整数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。

    Input

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

    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

    20%的数据中,m,n≤100; 40%的数据中,m,n≤1000; 100%的数据中,m,n≤10000。

     
    树套树
      1 #include<cstdio>
      2 #include<cstdlib>
      3 using namespace std;
      4 const int N=3000001,inf=1000000000;
      5 struct tree{int lch,rch,num,sz,w,rnd;}tr[N];
      6 int a[10010],n,m,sz,root[10010*4];
      7 void updata(int x){
      8     int l=tr[x].lch,r=tr[x].rch;
      9     tr[x].sz=tr[l].sz+tr[r].sz+tr[x].w;
     10 }
     11  
     12 void lturn(int &k)
     13 {int t=tr[k].rch;tr[k].rch=tr[t].lch;tr[t].lch=k;updata(k);updata(t);k=t;}
     14 void rturn(int &k)
     15 {int t=tr[k].lch;tr[k].lch=tr[t].rch;tr[t].rch=k;updata(k);updata(t);k=t;}
     16 void ins(int &k,int x){
     17     if(!k){
     18         k=++sz;tr[k].rnd=rand();tr[k].sz=1;tr[k].num=x;tr[k].w=1;return;
     19     }
     20     if(tr[k].num==x) tr[k].w++;
     21     else if(tr[k].num>x) {
     22         ins(tr[k].lch,x);
     23         if(tr[k].rnd>tr[tr[k].lch].rnd) rturn(k);
     24     }else{
     25         ins(tr[k].rch,x);
     26         if(tr[k].rnd>tr[tr[k].rch].rnd) lturn(k);
     27     }
     28     updata(k);
     29 }
     30  
     31 void insert(int k,int l,int r,int x,int y){
     32     if(l<=y&&r>=y) ins(root[k],x);
     33     if(l==r) return;
     34     int mid=(l+r)>>1;
     35     if(y>mid) insert(k<<1|1,mid+1,r,x,y);
     36     else insert(k<<1,l,mid,x,y);
     37 }
     38  
     39 int find(int k,int x){
     40     if(!k) return 0;
     41     int l=tr[k].lch,r=tr[k].rch;
     42     if(tr[k].num>x) return find(l,x);
     43     else if(tr[k].num<x) return find(r,x)+tr[l].sz+tr[k].w;
     44     else return tr[l].sz;
     45 }
     46  
     47 int get_rank(int k,int l,int r,int L,int R,int x){
     48     int mid=(l+r)>>1;
     49     if(l==L&&r==R) return find(root[k],x);
     50     if(R<=mid) return get_rank(k<<1,l,mid,L,R,x);
     51     else if(L>mid) return get_rank(k<<1|1,mid+1,r,L,R,x);
     52     else return get_rank(k<<1,l,mid,L,mid,x)+get_rank(k<<1|1,mid+1,r,mid+1,R,x);
     53 }
     54  
     55 int ask(int x,int y,int rk){
     56     int l=1,r=inf,mid=(l+r)>>1,ans=0;
     57     while(l<=r){
     58         mid=(l+r)>>1;
     59         int k=get_rank(1,1,n,x,y,mid);
     60         if(k<=rk) ans=mid,l=mid+1;
     61         else r=mid-1;
     62     }
     63     return ans;
     64 }
     65  
     66 void del(int &k,int p){
     67     if(tr[k].num==p){
     68         if(tr[k].w>1) tr[k].w--,tr[k].sz--;
     69         else{
     70             if(tr[k].lch*tr[k].rch==0) k=tr[k].lch+tr[k].rch;
     71             else if(tr[tr[k].lch].rnd<tr[tr[k].rch].rnd) rturn(k),del(k,p);
     72             else lturn(k),del(k,p);
     73         }
     74     }
     75     else{
     76         tr[k].sz--;
     77         if(tr[k].num>p) del(tr[k].lch,p);else del(tr[k].rch,p);
     78     }
     79 }
     80  
     81 void make(int &rt,int p,int t){
     82     ins(rt,t);
     83     del(rt,p);
     84 }
     85  
     86 void change(int k,int l,int r,int x,int p,int t){
     87     if(l<=x&&r>=x) make(root[k],p,t);
     88     if(l==r) return;
     89     int mid=(l+r)>>1;
     90     if(x<=mid) change(k<<1,l,mid,x,p,t);
     91     else change(k<<1|1,mid+1,r,x,p,t);
     92 }
     93  
     94 int main(){
     95     scanf("%d%d",&n,&m);
     96     for(int i=1;i<=n;i++){
     97         scanf("%d",&a[i]);
     98         insert(1,1,n,a[i],i);
     99     }
    100     char s[4];
    101     for(int i=1;i<=m;i++){
    102         scanf("%s",s);
    103         if(s[0]=='Q') {
    104             int l,r,rk;
    105             scanf("%d%d%d",&l,&r,&rk);
    106             printf("%d
    ",ask(l,r,rk-1));
    107         }else{
    108             int x,t;
    109             scanf("%d%d",&x,&t);
    110             change(1,1,n,x,a[x],t);
    111             a[x]=t;
    112         }
    113     }
    114 }

    树状数组+主席树

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #define N 2200001
     5 using namespace std;
     6 int n,m,tot,top,cnt;
     7 int v[10001],num[20001];
     8 int A[10001],B[10001],X[10001],root[10001],K[10001];
     9 int sz[N],ls[N],rs[N];
    10 int L[30],R[30],a,b;
    11 int lowbit(int x){return x&(-x);}
    12 void updata(int last,int l,int r,int &k,int x,int add){
    13     k=++cnt;
    14     int mid=(l+r)>>1;
    15     sz[k]=sz[last]+add;ls[k]=ls[last];rs[k]=rs[last];
    16     if(l==r) return;
    17     if(x<=mid) updata(ls[last],l,mid,ls[k],x,add);
    18     else updata(rs[last],mid+1,r,rs[k],x,add);
    19 }
    20  
    21 int query(int l,int r,int k){
    22     if(l==r) return l;
    23     int mid=(l+r)>>1;
    24     int suml=0,sumr=0;
    25     for(int i=1;i<=a;i++)suml+=sz[ls[L[i]]];
    26     for(int i=1;i<=b;i++)sumr+=sz[ls[R[i]]];
    27     if(sumr-suml>=k){
    28         for(int i=1;i<=a;i++) L[i]=ls[L[i]];
    29         for(int i=1;i<=b;i++) R[i]=ls[R[i]];
    30         return query(l,mid,k);
    31     }else{
    32         for(int i=1;i<=a;i++) L[i]=rs[L[i]];
    33         for(int i=1;i<=b;i++) R[i]=rs[R[i]];
    34         return query(mid+1,r,k-(sumr-suml));
    35     }
    36 }
    37  
    38 int main(){
    39     scanf("%d%d",&n,&m);
    40     for(int i=1;i<=n;i++){
    41         scanf("%d",&v[i]);
    42         num[++top]=v[i];
    43     }
    44     char opt[4];
    45     for(int i=1;i<=m;i++){
    46         scanf("%s%d%d",opt,&A[i],&B[i]);
    47         if(opt[0]=='Q') scanf("%d",&X[i]),K[i]=1;
    48         else num[++top]=B[i];
    49     }
    50     sort(num+1,num+top+1);
    51     tot=unique(num+1,num+top+1)-num-1;
    52     for(int i=1;i<=n;i++){
    53         int t=lower_bound(num+1,num+tot+1,v[i])-num;
    54         for(int j=i;j<=n;j+=lowbit(j))
    55             updata(root[j],1,tot,root[j],t,1);
    56     }
    57     for(int i=1;i<=m;i++){
    58         if(K[i]){
    59             a=0,b=0;A[i]--;
    60             for(int j=A[i];j>=1;j-=lowbit(j)) L[++a]=root[j];
    61             for(int j=B[i];j>=1;j-=lowbit(j)) R[++b]=root[j];
    62             printf("%d
    ",num[query(1,tot,X[i])]);
    63         }else{
    64             int t=lower_bound(num+1,num+tot+1,v[A[i]])-num;
    65             for(int j=A[i];j<=n;j+=lowbit(j)) 
    66             updata(root[j],1,tot,root[j],t,-1);
    67             v[A[i]]=B[i];
    68             t=lower_bound(num+1,num+tot+1,v[A[i]])-num;
    69             for(int j=A[i];j<=n;j+=lowbit(j)) 
    70             updata(root[j],1,tot,root[j],t,1);
    71         }
    72     }
    73 }

    整体二分

     1 #include<cstdio>
     2 const int inf=1000000000;
     3 struct node{int flag,x,y,no,rk,cur;}p[300100],p1[300100],p2[300010];
     4 int n,m,a[100010],cnt,sum,ans[100100],w[300010],tmp[300010],num;
     5  
     6 void add(int x,int y){
     7     for(int i=x;i<=n;i+=(i&(-i))) w[i]+=y; 
     8 } 
     9  
    10 int query(int x){
    11     int ans=0;
    12     for (int i=x;i>0;i-=(i&(-i))) ans+=w[i];
    13     return ans;
    14 }
    15  
    16 void divid(int h,int t,int l,int r){
    17     if(h>t) return;
    18     if(l==r) {for(int i=h;i<=t;i++) 
    19             ans[p[i].no]=l;return;} 
    20     int mid=(l+r)>>1;
    21     for(int i=h;i<=t;i++){
    22         if(p[i].flag==1&&p[i].y<=mid) add(p[i].x,1);
    23         else if(p[i].flag==2&&p[i].y<=mid) add(p[i].x,-1);
    24         else if(p[i].flag==3)tmp[i]=query(p[i].y)-query(p[i].x-1);
    25     }
    26     for(int i=h;i<=t;i++){
    27         if(p[i].flag==1&&p[i].y<=mid) add(p[i].x,-1);
    28         else if(p[i].flag==2&&p[i].y<=mid) add(p[i].x,1);
    29     }
    30     int l1=0,l2=0;
    31     for(int i=h;i<=t;i++){
    32         if(p[i].flag==3){
    33             if(tmp[i]+p[i].cur>p[i].rk-1) p1[++l1]=p[i];
    34             else p[i].cur+=tmp[i],p2[++l2]=p[i];
    35         }
    36         else {
    37             if(p[i].y<=mid) p1[++l1]=p[i];else p2[++l2]=p[i];
    38         }
    39     }
    40     for(int i=h;i<=l1+h-1;i++) p[i]=p1[i-h+1];
    41     for(int i=l1+h;i<=t;i++) p[i]=p2[i-l1-h+1];
    42     divid(h,l1+h-1,l,mid);
    43     divid(l1+h,t,mid+1,r);
    44 }
    45  
    46 int main(){
    47     scanf("%d%d",&n,&m);
    48     for(int i=1;i<=n;i++){
    49         scanf("%d",&a[i]);
    50         p[++cnt].flag=1;p[cnt].x=i;p[cnt].y=a[i];
    51     }
    52     for(int i=1;i<=m;i++){
    53         char opt[4];int x,y,k;
    54         scanf("%s%d%d",opt,&x,&y);
    55         if(opt[0]=='Q'){
    56             scanf("%d",&k);
    57             p[++cnt].x=x,p[cnt].y=y;p[cnt].flag=3;p[cnt].no=++num;
    58             p[cnt].rk=k;
    59         }else{
    60             p[++cnt].x=x;p[cnt].y=a[x];p[cnt].flag=2;
    61             a[x]=y;
    62             p[++cnt].x=x;p[cnt].y=a[x];p[cnt].flag=1;
    63         }
    64     }
    65     divid(1,cnt,0,inf);
    66     for(int i=1;i<=num;i++) printf("%d
    ",ans[i]);
    67 } 

    这就是时间差距。。。

  • 相关阅读:
    【Android N 7.1.1】 屏幕亮和灭的处理地方
    Android 测量调用方法耗时的方法
    【Android M】获取屏幕锁定的相关信息:“无”,“滑动”,“PIN码”,"图案","密码"
    【Android N 7.1.1】 ActivityManagerService 获取cpu状态
    Android 判断当前是否在跑monkey测试
    【Android N 7.1.1】 锁屏之上显示Toast
    【Android N 7.1.1】 处于锁屏界面时可以转屏
    【Android N 7】使用量统计usagestats
    #### 批处理命令 获取当前目录下所有文件的路径
    Linux命令 swap:内存交换空间
  • 原文地址:https://www.cnblogs.com/wuminyan/p/5229600.html
Copyright © 2020-2023  润新知