• 树链剖分学习


    两次dfs,第一次处理处fa[],depth[],size[],son[],第二次处理出top[],rank[],id[]

    一条重链的编号是连续的,可以用数据结构维护,做事情的时候判断是否在同一条链上,不是就把最深的跳到链头的fa[],然后继续判断

    luogu3384 【模板】树链剖分

    区间加,求和,子树加,求和

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int maxn=200005;
    inline int read(){
        int x=0,k=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') k=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return k*x;
    }
    int rt,cnt,ecnt,fir[maxn],nex[maxn],to[maxn];
    int f[maxn],d[maxn],size[maxn],son[maxn],rk[maxn],top[maxn],id[maxn],val[maxn];
    struct node{
        int l,r;
        ll v,add;
    }a[maxn*2];
    int n,m,R,opt,x,y;
    ll p,k;
    void build(int u,int l,int r){
        a[u].l=l;a[u].r=r;a[u].add=0;
        if(l==r) a[u].v=val[rk[l]];
        else{
            int mid=l+r>>1;
            build(u<<1,l,mid);
            build(u<<1|1,mid+1,r);
            a[u].v=a[u<<1].v+a[u<<1|1].v;
        }
    }
    void addd(int u,ll v){
        a[u].add+=v;
        a[u].add%=p;
        a[u].v+=(a[u].r-a[u].l+1)*v;
        a[u].v%=p;
    }
    void pushdown(int u){
            if(a[u].add){
            addd(u<<1,a[u].add);
            addd(u<<1|1,a[u].add);
            a[u].add=0;
        }
    }
    void update(int u,int l,int r,ll v){
        if(a[u].l==l&&a[u].r==r) addd(u,v);
        else{
            int mid=(a[u].l+a[u].r)>>1;
            pushdown(u);
            if(r<=mid) update(u<<1,l,r,v);
            else if(l>mid) update(u<<1|1,l,r,v);
            else update(u<<1,l,mid,v),update(u<<1|1,mid+1,r,v);
            a[u].v=a[u<<1].v+a[u<<1|1].v;
        }
    }
    ll query(int u,int l,int r){
        if(a[u].l==l&&a[u].r==r) return a[u].v;
        int mid=(a[u].l+a[u].r)>>1;
        pushdown(u);
        if(r<=mid) return query(u<<1,l,r);
        else if(l>mid) return query(u<<1|1,l,r);
        return (query(u<<1,l,mid)+query(u<<1|1,mid+1,r))%p; 
    }
    void addedge(int u,int v){
        nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;
    }
    void dfs1(int u,int fa,int depth){
        f[u]=fa;
        d[u]=depth;
        size[u]=1;
        for(int i=fir[u];i;i=nex[i]){
            int v=to[i];
            if(v==fa) continue;
            dfs1(v,u,depth+1);
            size[u]+=size[v];
            if(size[v]>size[son[u]]) son[u]=v;
        }
    }
    void dfs2(int u,int t){
        top[u]=t;
        id[u]=++cnt;
        rk[cnt]=u;
        if(!son[u]) return;
        dfs2(son[u],t);
        for(int i=fir[u];i;i=nex[i]){
            int v=to[i];
            if(v!=son[u]&&v!=f[u]) dfs2(v,v);
        }
    }
    int sum(int x,int y){
        int ans=0,fx=top[x],fy=top[y];
        while(fx!=fy){
            if(d[fx]>=d[fy]){
                ans+=query(1,id[fx],id[x]);
                ans%=p;
                x=f[fx];
            }
            else{
                ans+=query(1,id[fy],id[y]);
                ans%=p;
                y=f[fy];
            }
            fx=top[x];
            fy=top[y];
        }
        if(id[x]<=id[y]) ans+=query(1,id[x],id[y]),ans%=p;
        else ans+=query(1,id[y],id[x]),ans%=p;
    }
    void updates(int x,int y,int c){
        int fx=top[x],fy=top[y];
        while(fx!=fy){
            if(d[fx]>=d[fy]){
                update(1,id[fx],id[x],c);
                x=f[fx];
            }
            else{
                update(1,id[fy],id[y],c);
                y=f[fy];
            }
            fx=top[x];
            fy=top[y];
        }
        if(id[x]<=id[y]) update(1,id[x],id[y],c);
        else update(1,id[y],id[x],c);
    }
    int main(){
    //    freopen(".in","r",stdin);
    //    freopen(".out","w",stdout);
        cin>>n>>m>>R>>p;
        for(int i=1;i<=n;i++){
            val[i]=read();
        }
        for(int i=1;i<n;i++){
            int x,y;
            x=read();y=read();
            addedge(x,y);
            addedge(y,x);
        }
        cnt=0;
        dfs1(R,0,1);
        dfs2(R,R);
        cnt=1;
        build(1,1,n);
        for(int i=1;i<=m;i++){
            int opt,x,y,z;
            opt=read();
            if(opt==1){
                x=read();y=read();z=read();z%=p;
                updates(x,y,z);
            }
            else if(opt==2){
                x=read();y=read();
                cout<<sum(x,y)<<endl;
            }
            else if(opt==3){
                x=read();z=read();
                update(1,id[x],id[x]+size[x]-1,z%p);
            }
            else{
                x=read();
                cout<<query(1,id[x],id[x]+size[x]-1)<<endl;
            }
        }
        return 0;
    }
    View Code

    [JLOI2014]松鼠的新家 

    相当于n-1次+1,每次把a[i]~a[i+1]的区间+1,由于a[2]~a[n]会加两次,所以这些还要-1

    // luogu-judger-enable-o2
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int maxn=300005;
    const int maxm=600005;
    inline int read(){
        int x=0,k=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') k=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return k*x;
    }
    int rt,cnt,ecnt,fir[maxn],nex[maxm],to[maxm];
    int f[maxn],d[maxn],size[maxn],son[maxn],rk[maxn],top[maxn],id[maxn],val[maxn];
    struct node{
        int l,r;
        ll v,add;
    }a[maxm*2];
    int n,m,R,opt,x,y;
    ll p,k;
    void build(int u,int l,int r){
        a[u].l=l;a[u].r=r;a[u].add=0;
        if(l==r) return;
        else{
            int mid=l+r>>1;
            build(u<<1,l,mid);
            build(u<<1|1,mid+1,r);
            a[u].v=a[u<<1].v+a[u<<1|1].v;
        }
    }
    void addd(int u,ll v){
        a[u].add+=v;
        a[u].v+=(a[u].r-a[u].l+1)*v;
    }
    void pushdown(int u){
            if(a[u].add){
            addd(u<<1,a[u].add);
            addd(u<<1|1,a[u].add);
            a[u].add=0;
        }
    }
    void update(int u,int l,int r,ll v){
        if(a[u].l==l&&a[u].r==r) addd(u,v);
        else{
            int mid=(a[u].l+a[u].r)>>1;
            pushdown(u);
            if(r<=mid) update(u<<1,l,r,v);
            else if(l>mid) update(u<<1|1,l,r,v);
            else update(u<<1,l,mid,v),update(u<<1|1,mid+1,r,v);
            a[u].v=a[u<<1].v+a[u<<1|1].v;
        }
    }
    ll query(int u,int l,int r){
        if(a[u].l==l&&a[u].r==r) return a[u].v;
        int mid=(a[u].l+a[u].r)>>1;
        pushdown(u);
        if(r<=mid) return query(u<<1,l,r);
        else if(l>mid) return query(u<<1|1,l,r);
        return (query(u<<1,l,mid)+query(u<<1|1,mid+1,r)); 
    }
    void addedge(int u,int v){
        nex[++ecnt]=fir[u];fir[u]=ecnt;to[ecnt]=v;
    }
    void dfs1(int u,int fa,int depth){
        f[u]=fa;
        d[u]=depth;
        size[u]=1;
        for(int i=fir[u];i;i=nex[i]){
            int v=to[i];
            if(v==fa) continue;
            dfs1(v,u,depth+1);
            size[u]+=size[v];
            if(size[v]>size[son[u]]) son[u]=v;
        }
    }
    void dfs2(int u,int t){
        top[u]=t;
        id[u]=++cnt;
        rk[cnt]=u;
        if(!son[u]) return;
        dfs2(son[u],t);
        for(int i=fir[u];i;i=nex[i]){
            int v=to[i];
            if(v!=son[u]&&v!=f[u]) dfs2(v,v);
        }
    }
    int sum(int x,int y){
        int ans=0,fx=top[x],fy=top[y];
        while(fx!=fy){
            if(d[fx]>=d[fy]){
                ans+=query(1,id[fx],id[x]);
                ans%=p;
                x=f[fx];
            }
            else{
                ans+=query(1,id[fy],id[y]);
                ans%=p;
                y=f[fy];
            }
            fx=top[x];
            fy=top[y];
        }
        if(id[x]<=id[y]) ans+=query(1,id[x],id[y]);
        else ans+=query(1,id[y],id[x]);
    }
    void updates(int x,int y,int c){
        int fx=top[x],fy=top[y];
        while(fx!=fy){
            if(d[fx]>=d[fy]){
                update(1,id[fx],id[x],c);
                x=f[fx];
            }
            else{
                update(1,id[fy],id[y],c);
                y=f[fy];
            }
            fx=top[x];
            fy=top[y];
        }
        if(id[x]<=id[y]) update(1,id[x],id[y],c);
        else update(1,id[y],id[x],c);
    }
    int main(){
    //    freopen(".in","r",stdin);
    //    freopen(".out","w",stdout);
        n=read();
        for(int i=1;i<=n;i++) val[i]=read();
        for(int i=1;i<n;i++){
            int x,y;
            x=read();y=read();
            addedge(x,y);addedge(y,x);
        }
        dfs1(1,0,1);
        dfs2(1,1);
        build(1,1,n);
        for(int i=1;i<n;i++){
            updates(val[i],val[i+1],1);
            updates(val[i+1],val[i+1],-1);
        }
        for(int i=1;i<=n;i++){
            cout<<query(1,id[i],id[i])<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    HDOJ_ACM_超级楼梯
    HDOJ_ACM_下沙的沙子有几粒?
    杭电_ACM_How Many Trees
    HDOJ_ACM_Tiling_easy version
    HDOJ_ACM_母牛的故事
    HDOJ_ACM_小兔的棋盘
    HDOJ_ACM_一只小蜜蜂
    杭电_ACM_Count the Trees
    HDOJ_ACM_折线分割平面
    Sun Solaris下JAVA以及JSP开发环境的配制小记
  • 原文地址:https://www.cnblogs.com/silent-pyb/p/9808383.html
Copyright © 2020-2023  润新知