• 可修改主席树&树上可修改主席树—树套树套树!!!


    可修改主席树

    题目:

    Dynamic Rankings(洛谷2617)

    !思路:其实树上主席树是把每一棵主席树看做树状数组上的一个点,每次修改log棵主席树,求区间和的时候同样log查询前缀和。

    上代码!

    #include<bits/stdc++.h>
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=2e4+5;
    int n,m,rt[N],root[N],q[N],cnt,a[N],b[N],tot;
    struct node{int l,r,num;}t[N*100];
    struct data{int x,y,k;}Q[N];
    inline int getid(int x){return lower_bound(b+1,b+1+cnt,x)-b;}
    inline int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch-48;_()x=x*10+ch-48;return f*x;}
    void update(int l,int r,int &x,int y,int pos,int v){
        t[x=++tot]=t[y];t[x].num+=v;
        if(l==r)return;int mid=(l+r)>>1;
        if(pos<=mid)update(l,mid,t[x].l,t[y].l,pos,v);
        else update(mid+1,r,t[x].r,t[y].r,pos,v);
    }
    inline void change(int p,int v){
        for(int i=p;i<=n;i+=i&-i)update(1,cnt,rt[i],rt[i],a[p],v);
    }
    inline int cal(int x){
        int sum=0;
        for(int i=x;i;i-=i&-i)sum+=t[t[q[i]].l].num;return sum;
    }
    inline int query(int x,int y,int k){
        for(int i=x;i;i-=i&-i)q[i]=rt[i];
        for(int i=y;i;i-=i&-i)q[i]=rt[i];
        int l=1,r=cnt,qx=x,qy=y;x=root[x];y=root[y];
        while(l<r){
            int sum=cal(qy)-cal(qx)+t[t[y].l].num-t[t[x].l].num;
            int mid=(l+r)>>1;
            if(k<=sum){
                for(int i=1;i<=n;i++)q[i]=t[q[i]].l;
                x=t[x].l;y=t[y].l;r=mid;
            }
            else{
                for(int i=1;i<=n;i++)q[i]=t[q[i]].r;
                x=t[x].r;y=t[y].r;l=mid+1;k-=sum;
            }
        }
        return l;
    }
    int main()
    {
      n=read();m=read();for(int i=1;i<=n;i++)a[i]=read(),b[i]=a[i];cnt=n;
      for(int i=1;i<=m;i++){
          char ch;cin>>ch;
          if(ch=='Q')Q[i].x=read(),Q[i].y=read(),Q[i].k=read();
          if(ch=='C')Q[i].x=read(),Q[i].k=read(),b[++cnt]=Q[i].k;
        }
        sort(b+1,b+1+cnt);cnt=unique(b+1,b+1+cnt)-b-1;for(int i=1;i<=n;i++)a[i]=getid(a[i]);
        for(int i=1;i<=n;i++)update(1,cnt,root[i],root[i-1],a[i],1);
        for(int i=1;i<=m;i++){
            if(Q[i].y==0){
                change(Q[i].x,-1);a[Q[i].x]=getid(Q[i].k);change(Q[i].x,1);
            }
            else{
                printf("%d
    ",b[query(Q[i].x-1,Q[i].y,Q[i].k)]);
            }
        }
      return 0;
    }
    View Code

    接下来就是调了一天的树上可修改主席树

    题目:

    网络管理Network

    其实就是树上主席树与可修改主席树的结合,(至于为什么我调了一天,因为我弱阿,理直气壮!)。

    这份代码还是要常常温习啊,懒得打注释,希望我下次还记得我是怎么写的qaq

    #include<bits/stdc++.h>
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=80005;
    int n,m,d[N],fa[N][22],head[N],ne[N<<1],to[N<<1],cnt,tot,rt[N],q[N],a[N],b[N<<1],vis[N],dfn[N],tt,num[N],sz[N];
    struct node{int l,r,num;}t[N*120];struct data{int k,a,b;}Q[N];
    inline int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch-48;_()x=x*10+ch-48;return f*x;}
    inline void insert(int u,int v){ne[++tot]=head[u];head[u]=tot;to[tot]=v;}
    inline int getid(int x){return lower_bound(b+1,b+1+cnt,x)-b;}
    void update(int l,int r,int &x,int y,int pos,int v){
        if(!x)x=++tot;t[x]=t[y];t[x].num+=v;
        if(l==r)return;int mid=(l+r)>>1;
        if(pos<=mid)update(l,mid,t[x].l,t[y].l,pos,v);
        else update(mid+1,r,t[x].r,t[y].r,pos,v);
    }
    void dfs(int x){
        //update(1,cnt,root[x],root[fa[x][0]],a[x],1);
        dfn[x]=++tt;num[tt]=x;sz[x]=1;
        for(int i=head[x];i;i=ne[i]){
            if(to[i]==fa[x][0])continue;
            d[to[i]]=d[x]+1;fa[to[i]][0]=x;
            dfs(to[i]);sz[x]+=sz[to[i]];
        }
    }
    inline int Lca(int x,int y){
        if(d[x]<d[y])swap(x,y);
        for(int i=20;i>=0;i--)if(d[fa[x][i]]>=d[y])x=fa[x][i];
        if(x==y)return x;
        for(int i=20;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
        return fa[x][0];
    }
    inline void change(int p,int x,int v){//if(dfn[p]==0)printf("#%d %d %d ",p,x,sz[x]);
        for(int i=dfn[p];i<=n;i+=i&-i)update(1,cnt,rt[i],rt[i],a[x],v);
    }
    inline void getq(int x){for(int i=dfn[x];i;i-=i&-i)q[i]=rt[i],vis[i]=1;}
    inline int cal(int x){int sum=0;for(int i=dfn[x];i;i-=i&-i)sum+=t[t[q[i]].l].num,vis[i]=0;return sum;}
    inline void cagl(int x){for(int i=dfn[x];i;i-=i&-i)if(!vis[i])q[i]=t[q[i]].l,vis[i]=1;}
    inline void cagr(int x){for(int i=dfn[x];i;i-=i&-i)if(!vis[i])q[i]=t[q[i]].r,vis[i]=1;}
    inline int query(int x,int y,int a,int b,int k){
      getq(x);getq(y);getq(a);getq(b);//printf("#");
        int l=1,r=cnt,sum;
        while(l<r){
            int mid=(l+r)>>1;
            sum=cal(x)+cal(y)-cal(a)-cal(b);
            if(k<=sum){
                cagl(x);cagl(y);cagl(a);cagl(b);r=mid;
            }
            else{
                cagr(x);cagr(y);cagr(a);cagr(b);l=mid+1;k-=sum;
            }
        }
        return l;
    }
    int main()
    {
      n=read();m=read();for(int i=1;i<=n;i++)a[i]=read(),b[i]=a[i];cnt=n;
      for(int i=1;i<n;i++){int x,y;x=read();y=read();insert(x,y);insert(y,x);}tot=0;
      for(int i=1;i<=m;i++){
          Q[i].k=read();Q[i].a=read();Q[i].b=read();
          if(Q[i].k==0)b[++cnt]=Q[i].b;
        }
        sort(b+1,b+1+cnt);cnt=unique(b+1,b+1+cnt)-b-1;for(int i=1;i<=n;i++)a[i]=getid(a[i]);dfn[n+1]=n+1;num[n+1]=n+1;
        d[1]=1;dfs(1);for(int i=1;i<=20;i++)for(int j=1;j<=n;j++)fa[j][i]=fa[fa[j][i-1]][i-1];
        for(int i=1;i<=n;i++){change(i,i,1);change(num[dfn[i]+sz[i]],i,-1);}
        for(int i=1;i<=m;i++){
            if(Q[i].k==0){
              change(Q[i].a,Q[i].a,-1);change(num[dfn[Q[i].a]+sz[Q[i].a]],Q[i].a,1);
                a[Q[i].a]=getid(Q[i].b);change(Q[i].a,Q[i].a,1);change(num[dfn[Q[i].a]+sz[Q[i].a]],Q[i].a,-1);
            }
            else {
                int lca=Lca(Q[i].a,Q[i].b);int k=d[Q[i].a]+d[Q[i].b]-2*d[lca]-Q[i].k+2;
                if(k<1){puts("invalid request!");continue;}
                printf("%d
    ",b[query(Q[i].a,Q[i].b,lca,fa[lca][0],k)]);
            }
        }
      return 0;
    }
    View Code

    似乎还可以用树剖套主席树套树状数组...

  • 相关阅读:
    Socket
    属性的使用案例
    link.bat
    未命名 (2)
    解决wordpress3.5更新插件和主题失败的问题
    解除文件锁定(此文件来自其他计算机,可能被阻止以保护该计算机)
    String转换成Integer源码分析
    实战体会Java多线程编程精要
    JAVA进阶:一个简单Thread缓冲池的实现
    Java对象的序列化和反序列化实践
  • 原文地址:https://www.cnblogs.com/Jessie-/p/9440012.html
Copyright © 2020-2023  润新知