蓝书上的树剖用不习惯,今日发现一篇julao的树剖题解,格式工整,简单易记,富有条理,因此学习之。

原题:GO

julao的blog:GO


具体的不讲了,直接上代码吧(已经过我的码风熏陶)

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,m,r,mod,tot,ans;
int w[N],dep[N],siz[N],fa[N],son[N],top[N],id[N],w2[N];
int at[N<<1],sum[N<<1];
inline int read(){
    int f=1,x=0;
    char c=getchar();
    while(!isdigit(c)){
        if(c=='-') f=-1;
        c=getchar();
    }
    while(isdigit(c)){
        x=x*10+c-'0';
        c=getchar();
    }
    return x*f;
}
int head[N],cnt;
struct edge{ int to,next; }e[N<<1];
inline void addedge(int from,int to){ e[++cnt]=(edge){to,head[from]};head[from]=cnt; }
inline void add(int x,int y){addedge(x,y),addedge(y,x);}
void dfs1(int u,int f){
    dep[u]=dep[f]+1;
    siz[u]=1;
    fa[u]=f;
    int maxson=0;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(v==f) continue;
        dfs1(v,u);
        siz[u]+=siz[v];
        if(siz[v]>maxson) maxson=siz[v],son[u]=v;
    }
}
void dfs2(int u,int f){
    id[u]=++tot;
    w2[tot]=w[u];
    top[u]=f;
    if(!son[u]) return;
    dfs2(son[u],f);
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(v==fa[u]||v==son[u]) continue;
        dfs2(v,v);
    }
}

inline int ls(int o){return o<<1;}
inline int rs(int o){return o<<1|1;}
inline void pd(int o,int l,int r,int num){
    at[o]+=num;
    sum[o]+=(r-l+1)*num;
    sum[o]%=mod;
}
inline void pushdown(int o,int l,int r){
    int mid=(l+r)>>1;
    pd(ls(o),l,mid,at[o]);
    pd(rs(o),mid+1,r,at[o]);
    at[o]=0;
}
inline void pushup(int o){
    sum[o]=(sum[ls(o)]+sum[rs(o)])%mod;
}
void build(int o,int l,int r){
    if(l==r){
        sum[o]=w2[l];
        if(sum[o]>mod) sum[o]%=mod;
        return;
    }
    int mid=(l+r)>>1;
    build(ls(o),l,mid);
    build(rs(o),mid+1,r);
    pushup(o);
}
void change(int o,int l,int r,int x,int y,int k){
    if(l>y||r<x) return;
    if(x<=l&&r<=y){
        sum[o]+=(r-l+1)*k;
        at[o]+=k;
        return;
    }
    int mid=(l+r)>>1;
    pushdown(o,l,r);
    if(x<=mid) change(ls(o),l,mid,x,y,k);
    if(y>mid) change(rs(o),mid+1,r,x,y,k);
    pushup(o);
}
void query(int o,int l,int r,int x,int y){
    if(l>y||r<x) return;
    if(x<=l&&r<=y){
        ans+=sum[o];
        ans%=mod;
        return;
    }
    int mid=(l+r)>>1;
    pushdown(o,l,r);
    if(x<=mid) query(ls(o),l,mid,x,y);
    if(y>mid) query(rs(o),mid+1,r,x,y);
}
inline int ask(int u,int v){
    int cur=0;
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        ans=0;
        query(1,1,n,id[top[u]],id[u]);
        cur+=ans;
        cur%=mod;
        u=fa[top[u]];
    }
    ans=0;
    if(dep[u]>dep[v]) swap(u,v);
    query(1,1,n,id[u],id[v]);
    cur+=ans;
    return cur%mod;
}
inline void ask2(int u,int v,int k){
    k%=mod;
    while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]]) swap(u,v);
        change(1,1,n,id[top[u]],id[u],k);
        u=fa[top[u]];
    }
    if(dep[u]>dep[v]) swap(u,v);
    change(1,1,n,id[u],id[v],k);
}
int main(){
    n=read();m=read();r=read();mod=read();
    for(register int i=1;i<=n;i++) w[i]=read();
    int k,x,y,z;
    for(register int i=1;i<n;i++) add(read(),read());
    dfs1(r,0);
    dfs2(r,r);
    build(1,1,n);
    for(register int i=1;i<=m;i++){
        k=read();
        if(k==1){
            x=read();y=read();z=read();
            ask2(x,y,z);
        }
        else if(k==2){
            x=read();y=read();
            printf("%d\n",ask(x,y));
        }
        else if(k==3){
            x=read();z=read();
            change(1,1,n,id[x],id[x]+siz[x]-1,z);
        }
        else{
            x=read();ans=0;
            query(1,1,n,id[x],id[x]+siz[x]-1);
            printf("%d\n",ans);
        }
    }
    return 0;
} 
02-01 06:59