20Pts树剖求助

P3384 【模板】重链剖分/树链剖分

SilverLi @ 2023-04-19 18:37:31

Record

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,m,r,mod,a[N];
int dfn[N],Index;
int fa[N],d[N],top[N];
int son[N],si[N];
vector<int>g[N];

// ---------- BIT

int t1[N],t2[N];
inline void add_in(int k,int v) {int v1=v*k;while(k<=n) t1[k]+=v,t2[k]+=v1,k+=k&-k;}
inline void add(int l,int r,int v) {add_in(l,v),add_in(r+1,-v);}
inline int sum_in(int k,int *t) {int res=0;while(k)   res+=t[k],k-=k&-k;return res;}
inline int sum(int l,int r) {return (r+1)*sum_in(r,t1)-l*sum_in(l-1,t1)-(sum_in(r,t2)-sum_in(l-1,t2));}

// ---------- init

void dfs(int v,int f) {
    d[v]=d[f]+1,si[v]=1,fa[v]=f;
    int mx=0;
    for(int i:g[v])
        if(i!=f) {
            dfs(i,v),si[v]+=si[i];
            if(mx<si[i])    son[v]=i,mx=si[i];
        }
}
void dfs2(int v,int deep) {
    dfn[v]=++Index,top[v]=deep;
    add(Index,Index,a[v]);
    if(!son[v]) return;
    dfs2(son[v],deep);
    for(int i:g[v])
        if(i!=fa[v]&&i!=son[v]) dfs2(i,i);
}

// ---------- Ê÷ÆÊ

inline void change(int u,int v,int ch) {
    while(top[u]!=top[v]) {
        if(d[top[u]]<d[top[v]]) swap(u,v);
        add(dfn[top[u]],dfn[u],ch);
        u=fa[top[u]];
    }
    if(d[u]>d[v])   swap(u,v);
    add(dfn[u],dfn[v],ch);
}
inline void changesub(int u,int ch) {add(dfn[u],dfn[u]+si[u]-1,ch);}
inline int ans(int u,int v) {
    int res=0;
    while(top[u]!=top[v]) {
        if(d[top[u]]<d[top[v]]) swap(u,v);
        res+=sum(top[u],u);res%=mod;
        u=fa[top[u]];
    }
    if(d[u]>d[v])   swap(u,v);
    res+=sum(dfn[u],dfn[v]);
    return res%mod;
}
inline int anssub(int u) {return sum(dfn[u],dfn[u]+si[u]-1)%mod;}
signed main() {
    cin>>n>>m>>r>>mod;
    for(int i=1;i<=n;++i)   cin>>a[i];
    for(int i=1;i<n;++i) {int x,y;cin>>x>>y;g[x].push_back(y),g[y].push_back(x);}
    dfs(r,0);dfs2(r,r);
    //for(int i=1;i<=n;++i)   add(dfn[i],dfn[i],a[i]);
    while(m--) {
        int opt,x,y,z;
        cin>>opt>>x;
        if(opt==1) {
            cin>>y>>z;
            change(x,y,z);
        } else if(opt==2) {
            cin>>y;
            cout<<ans(x,y)<<endl;
        } else if(opt==3) {
            cin>>z;
            changesub(x,z);
        } else  cout<<anssub(x)<<endl;
    }
    return 0;
}

|