• 【bzoj1901】dynamic ranking(带修改主席树)


    传送门(权限)

    传送门(非权限)

    花了一晚上总算把代码调好了……才知道待修改主席树怎么操作……

    然而还是一知半解orz……

    先说说我的理解吧

    我们一般建主席树的时候都是直接在序列上建的

    但是如果有修改操作怎么办?

    因为主席树维护的是前缀和

    而树状数组刚好支持待修改前缀和

    所以我们可以将主席树和树状数组一起使用

    树状数组实际指向主席树上的节点

    修改和查询操作用树状数组遍历,实则修改或查询主席树上的节点

     1 //minamoto
     2 #include<bits/stdc++.h>
     3 #define N 10005
     4 using namespace std;
     5 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
     6 char buf[1<<21],*p1=buf,*p2=buf;
     7 inline int read(){
     8     #define num ch-'0'
     9     char ch;bool flag=0;int res;
    10     while(!isdigit(ch=getc()))
    11     (ch=='-')&&(flag=true);
    12     for(res=num;isdigit(ch=getc());res=res*10+num);
    13     (flag)&&(res=-res);
    14     #undef num
    15     return res;
    16 }
    17 char obuf[1<<24],*o=obuf;
    18 void print(int x){
    19     if(x>9) print(x/10);
    20     *o++=x%10+48;
    21 }
    22 inline int lowbit(int x){return x&(-x);}
    23 int sum[N*600],L[N*600],R[N*600];
    24 int xx[N],yy[N],rt[N],a[N],b[N<<1],ca[N],cb[N],cc[N];
    25 int n,q,m,cnt=0,totx,toty;
    26 void update(int last,int &now,int l,int r,int x,int v){
    27     sum[now=++cnt]=sum[last]+v;
    28     L[now]=L[last],R[now]=R[last];
    29     if(l==r) return;
    30     int mid=(l+r)>>1;
    31     if(x<=mid) update(L[last],L[now],l,mid,x,v);
    32     else update(R[last],R[now],mid+1,r,x,v);
    33 }
    34 int query(int l,int r,int q){
    35     if(l==r) return l;
    36     int x=0,mid=(l+r)>>1;
    37     for(int i=1;i<=totx;++i) x-=sum[L[xx[i]]];
    38     for(int i=1;i<=toty;++i) x+=sum[L[yy[i]]];
    39     if(q<=x){
    40         for(int i=1;i<=totx;++i) xx[i]=L[xx[i]];
    41         for(int i=1;i<=toty;++i) yy[i]=L[yy[i]];
    42         return query(l,mid,q);
    43     }
    44     else{
    45         for(int i=1;i<=totx;++i) xx[i]=R[xx[i]];
    46         for(int i=1;i<=toty;++i) yy[i]=R[yy[i]];
    47         return query(mid+1,r,q-x);
    48     }
    49 }
    50 void add(int x,int y){
    51     int k=lower_bound(b+1,b+1+m,a[x])-b;
    52     for(int i=x;i<=n;i+=lowbit(i)) update(rt[i],rt[i],1,m,k,y);
    53 }
    54 int main(){
    55     //freopen("testdata.in","r",stdin);
    56     n=read(),q=read();
    57     for(int i=1;i<=n;++i)
    58     b[++m]=a[i]=read();
    59     for(int i=1;i<=q;++i){
    60         char ch;
    61         while(!isupper(ch=getc()));
    62         ca[i]=read(),cb[i]=read();
    63         if(ch=='Q') cc[i]=read();else b[++m]=cb[i];
    64     }
    65     sort(b+1,b+1+m);
    66     m=unique(b+1,b+1+m)-b-1;
    67     for(int i=1;i<=n;++i) add(i,1);
    68     for(int i=1;i<=q;++i){
    69         if(cc[i]){
    70             totx=toty=0;
    71             for(int j=ca[i]-1;j;j-=lowbit(j)) xx[++totx]=rt[j];
    72             for(int j=cb[i];j;j-=lowbit(j)) yy[++toty]=rt[j];
    73             print(b[query(1,m,cc[i])]),*o++='
    ';
    74         }
    75         else{add(ca[i],-1),a[ca[i]]=cb[i],add(ca[i],1);}
    76     }
    77     fwrite(obuf,o-obuf,1,stdout);
    78     return 0;
    79 }

    然而我太菜了不会树套树和整体二分……

    这里是zcysky大佬的树套树

    这里是will大爷的整体二分

  • 相关阅读:
    高通电池曲线(转)
    随笔分类
    海思uboot启动流程详细分析(转)
    GPRS以TCP上传数据到服务器OK,但收不到服务器下发的数据
    WIS800C TCP Client 非透传模式连接远程服务器使用方法(转)
    MySQL 不允许从远程访问的解决方法
    Linux下将Mysql和Apache加入到系统服务里的方法
    linux服务器出现严重故障后的原因以及解决方法
    Linux防火墙该如何设置
    Linux下的两个聊天命令的使用方法
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9393974.html
Copyright © 2020-2023  润新知