zoukankan      html  css  js  c++  java
  • 【bzoj1901】dynamic ranking(带修改主席树/树套树)

    题面地址(权限题)

    不用权限题的地址

    首先说说怎么搞带修改主席树?

    回忆一般的kth问题,我们的主席树求的是前缀和,这样我们在目标区间的左右端点的主席树差分下就能求出kth。

    那么我们如何支持修改操作?

    考虑到我们之前使用主席树朴素的维护区间前缀和,支持修改的话,只要把前缀和交给擅长它的树状数组维护,主席树只要维护下大概位置就好。

    当然维护位置最好要离散化一下。我校某高傲的dalao直接写CTSC那道树上动态Kth,并且niubi地手写哈希维护。

    别问我了在我写这篇文章的时候他还在debug呢。

    由于我比较菜,只能先把这个区间的写了,并且我太菜只能lower_bound和unique……

    代码学习的网上dalao以及hzwer。

     1 #include<bits/stdc++.h>
     2 #define N 10005
     3 using namespace std;
     4 inline int lowbit(int x){return x&-x;}
     5 int n,m,sz,totn,totx,toty,a[N],b[N<<1],ca[N],cb[N],cc[N];
     6 int xx[N],yy[N],rt[N],size[600*N],ls[600*N],rs[600*N];
     7 void ins(int &o,int l,int r,int x,int q,int v){
     8     o=++sz;size[o]=size[x]+v;ls[o]=ls[x];rs[o]=rs[x];
     9     if(l==r)return;int mid=(l+r)>>1;
    10     if(q<=mid)ins(ls[o],l,mid,ls[x],q,v);
    11     else ins(rs[o],mid+1,r,rs[x],q,v);
    12 }
    13 int query(int l,int r,int q){
    14     if(l==r)return l;
    15     int sum=0,mid=(l+r)>>1;
    16     for(int i=1;i<=totx;i++)sum-=size[ls[xx[i]]];
    17     for(int i=1;i<=toty;i++)sum+=size[ls[yy[i]]];
    18     if(q<=sum){
    19         for(int i=1;i<=totx;i++)xx[i]=ls[xx[i]];
    20         for(int i=1;i<=toty;i++)yy[i]=ls[yy[i]];
    21         return query(l,mid,q);
    22     }
    23     else{
    24         for(int i=1;i<=totx;i++)xx[i]=rs[xx[i]];
    25         for(int i=1;i<=toty;i++)yy[i]=rs[yy[i]];
    26         return query(mid+1,r,q-sum);
    27     }
    28 }
    29 void add(int x,int v){
    30     int k=lower_bound(b+1,b+totn+1,a[x])-b;
    31     for(int i=x;i<=n;i+=lowbit(i))ins(rt[i],1,totn,rt[i],k,v);
    32 }
    33 inline int read(){
    34     int f=1,x=0;char ch;
    35     do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    36     do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    37     return f*x;
    38 }
    39 int main(){char s[20];
    40     n=read();m=read();
    41     for(int i=1;i<=n;i++)a[i]=read(),b[++totn]=a[i];
    42     for(int i=1;i<=m;i++){
    43         scanf("%s",s);ca[i]=read();cb[i]=read();
    44         if(s[0]=='Q')cc[i]=read();else b[++totn]=cb[i];
    45     }
    46     sort(b+1,b+totn+1);
    47     totn=unique(b+1,b+totn+1)-b-1;
    48     for(int i=1;i<=n;i++)add(i,1);
    49     for(int i=1;i<=m;i++){
    50         if(cc[i]){
    51             totx=toty=0;
    52             for(int j=ca[i]-1;j;j-=lowbit(j))xx[++totx]=rt[j];
    53             for(int j=cb[i];j;j-=lowbit(j))yy[++toty]=rt[j];
    54             printf("%d
    ",b[query(1,totn,cc[i])]);
    55         }
    56         else{add(ca[i],-1);a[ca[i]]=cb[i];add(ca[i],1);}
    57     }
    58 }

    啊当然树套树也是可以的啦。

     1 #include<bits/stdc++.h>
     2 #define N 200001
     3 #define M 1300001
     4 #define inf 1000000007
     5 using namespace std;
     6 int n,m,tmp,a[N>>1],rt[N],sz,size[M],ls[M],rs[M],val[M],w[M],rnd[M];
     7 inline void pushup(int x){
     8     //in Treap
     9     size[x]=size[ls[x]]+size[rs[x]]+w[x];
    10 }
    11 void rturn(int &k)
    12 {int t=ls[k];ls[k]=rs[t];rs[t]=k;size[t]=size[k];pushup(k);k=t;}
    13 void lturn(int &k)
    14 {int t=rs[k];rs[k]=ls[t];ls[t]=k;size[t]=size[k];pushup(k);k=t;}
    15 void ins(int &k,int x){// in Treap
    16     if(!k){
    17         k=++sz;size[k]=1;w[k]=1;ls[k]=0;rs[k]=0;rnd[k]=rand();val[k]=x;return;
    18     }
    19     size[k]++;if(val[k]==x)w[k]++;
    20     else if(x<val[k]){ins(ls[k],x);if(rnd[ls[k]]<rnd[k])rturn(k);}
    21     else{ins(rs[k],x);if(rnd[rs[k]]<rnd[k])lturn(k);}
    22 }
    23 void del(int &k,int x){// in Treap
    24     if(val[k]==x){
    25         if(w[k]>1){w[k]--;size[k]--;return;}
    26         if(ls[k]*rs[k]==0)k=ls[k]+rs[k];
    27         else if(rnd[ls[k]]<rnd[rs[k]]){rturn(k);del(k,x);}
    28         else{lturn(k);del(k,x);}
    29     }
    30     else if(x<val[k]){del(ls[k],x);size[k]--;}
    31     else{del(rs[k],x);size[k]--;}
    32 }
    33 
    34 void change(int o,int l,int r,int q,int num,int v){
    35     // in Segment Tree
    36     del(rt[o],v);ins(rt[o],num);
    37     if(l==r)return;
    38     int mid=(l+r)>>1;
    39     if(q<=mid)change(o<<1,l,mid,q,num,v);
    40     else change(o<<1|1,mid+1,r,q,num,v);
    41 }
    42 void build(int o,int l,int r,int q,int num){
    43     ins(rt[o],num);if(l==r)return;
    44     int mid=(l+r)>>1;
    45     if(q<=mid)build(o<<1,l,mid,q,num);
    46     else build(o<<1|1,mid+1,r,q,num);
    47 }
    48 void find(int k,int x){
    49     if(!k)return;
    50     if(val[k]<=x){tmp+=size[ls[k]]+w[k];find(rs[k],x);}
    51     else find(ls[k],x);
    52 }
    53 void query(int o,int l,int r,int ql,int qr,int v){
    54     if(ql<=l&&r<=qr){find(rt[o],v);return;}
    55     int mid=(l+r)>>1;
    56     if(ql<=mid)query(o<<1,l,mid,ql,qr,v);
    57     if(qr>mid)query(o<<1|1,mid+1,r,ql,qr,v);
    58 }
    59 inline int read(){
    60     int f=1,x=0;char ch;
    61     do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
    62     do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
    63     return f*x;
    64 }
    65 char s[20];
    66 int main(){
    67     int T=read();
    68     while(T--){
    69         memset(rt,0,sizeof(rt));sz=0;
    70         n=read();m=read();
    71         for(int i=1;i<=n;i++)a[i]=read();
    72         for(int i=1;i<=n;i++)build(1,1,n,i,a[i]);
    73         for(int i=1;i<=m;i++){
    74             scanf("%s",s);
    75             if(s[0]=='C'){
    76                 int x=read(),y=read();
    77                 change(1,1,n,x,y,a[x]);
    78                 a[x]=y;
    79             }
    80             else{
    81                 int x=read(),y=read(),z=read();
    82                 int l=0,r=inf;
    83                 while(l<=r){
    84                     int mid=(l+r)>>1;
    85                     tmp=0;query(1,1,n,x,y,mid);
    86                     if(tmp>=z)r=mid-1;else l=mid+1;
    87                 }
    88                 printf("%d
    ",l);
    89             }
    90         }
    91     }
    92     return 0;
    93 }

    其实这个树套树只要分清楚维护范围,也不是很难写的那种。

    不过对于这种恶心的数据结构题,整体二分也是可以做到的。

    这里是will大爷写的整体二分的题解。

    zzq wc-ctsc-apio-NOI Au;yql精通多项式;zyz精通女装;由乃精通数据结构;孔老师是毒奶大师;我没有学上:我们都有光明的前途。
  • 相关阅读:
    模仿JavaAppArguments.java示例,编写一个程序,此程序从命令行接收多个数 字,求和之后输出结果,写出其的设计思想、程序流程图、源程序代码。
    大道至简第二章读后感
    大道至简第一章读后感
    md5实现
    jdk-动态代理
    使用反射复制对象
    java-二分查找法
    java-base64
    cxf框架使用(一)
    Freemarket学习笔记(一)
  • 原文地址:https://www.cnblogs.com/zcysky/p/6832876.html
Copyright © 2011-2022 走看看