树剖 wa on #9 求调

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

Luner @ 2024-11-04 18:00:10

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define L(i,l,r) for(int i=l;i<=r;i++)
#define R(i,r,l) for(int i=r;i>=l;i--)
const int N=1e5+10,M=2e5+10;
int n,m,root,MOD;
int head[N],to[M],nxt[M],v[N],idx;
int timestamp,vt[N],id[N];
int depth[N],hson[N],fa[N],siz[N],top[N];
void add(int u,int v) {
    to[idx]=v;
    nxt[idx]=head[u];
    head[u]=idx++;
}
struct Node {
    int l,r;
    int d,lzy;
};
struct SEG {
#define ls (u<<1)
#define rs (u<<1|1)
    Node tr[N<<2];
    void pushup(int u) {
        tr[u].d=(tr[ls].d+tr[rs].d)%MOD;
    }
    void build(int u,int l,int r) {
        if(l==r) {
            tr[u]= {l,r,vt[l]%MOD,0};
            return;
        }
        tr[u]= {l,r};
        int mid=l+r>>1;
        build(ls,l,mid);
        build(rs,mid+1,r);
        pushup(u);
    }
    void maketag(int u,int x) {
        int l=tr[u].l,r=tr[u].r;
        int len=r-l+1;
        tr[u].lzy=(tr[u].lzy+x)%MOD;
        tr[u].d=(tr[u].d+len*x%MOD)%MOD;
    }
    void pushdown(int u) {
        if(tr[u].lzy) {
            maketag(ls,tr[u].lzy);
            maketag(rs,tr[u].lzy);
            tr[u].lzy=0;
        }
    }
    int query(int u,int l,int r) {
        if(tr[u].l>=l&&tr[u].r<=r) {
            return tr[u].d;
        }
        pushdown(u);
        int res=0,mid=tr[u].l+tr[u].r>>1;
        if(l<=mid) res=(res+query(ls,l,r))%MOD;
        if(r>mid) res=(res+query(rs,l,r))%MOD;
        return res;
    }
    void update(int u,int l,int r,int x) {
        if(tr[u].l>=l&&tr[u].r<=r) {
            maketag(u,x);
            return;
        }
        pushdown(u);
        int res=0,mid=tr[u].l+tr[u].r>>1;
        if(l<=mid) update(ls,l,r,x);
        if(r>mid) update(rs,l,r,x);
        pushup(u);
    }
} T;
void dfs1(int u,int f,int dep) {
    fa[u]=f;
    depth[u]=dep;
    siz[u]=1; // !
    int mx=-1;
    for(int i=head[u]; ~i; i=nxt[i]) {
        int v=to[i];
        if(v==f) continue; // !
        dfs1(v,u,dep+1);
        siz[u]=(siz[u]+siz[v])%MOD;
        if(siz[v]>mx) {
            mx=siz[v];
            hson[u]=v;
        }
    }
}
void dfs2(int u,int tp) {
    id[u]=++timestamp;
    vt[timestamp]=v[u];
    top[u]=tp;
    if(!hson[u]) return;
    dfs2(hson[u],tp);
    for(int i=head[u]; ~i; i=nxt[i]) {
        int v=to[i];
        if(v==fa[u]||v==hson[u]) continue;
        dfs2(v,v); // ! 轻儿子为重链链头
    }
}
int qSon(int u) {
    return T.query(1,id[u],id[u]+siz[u]-1)%MOD;
}
void updSon(int u,int x) {
    T.update(1,id[u],id[u]+siz[u]-1,x);
}
int qLine(int u,int v) {
    int res=0;
    while(top[u]!=top[v]) {
        if(depth[top[u]]<depth[top[v]]) swap(u,v);
        res=(res+T.query(1,id[top[u]],id[u]))%MOD;
        u=fa[top[u]];
    }
    if(depth[u]>depth[v]) swap(u,v);
    res=(res+T.query(1,id[u],id[v]))%MOD;
    return res;
}
void updLine(int u,int v,int x) {
    x%=MOD;
    while(top[u]!=top[v]) {
        if(depth[top[u]]<depth[top[v]]) swap(u,v);
        T.update(1,id[top[u]],id[u],x); // id[top[u]] 的编号小于 id[u]
        u=fa[top[u]];
    }
    if(depth[u]>depth[v]) swap(u,v);
    T.update(1,id[u],id[v],x);
}
signed main() {
//  freopen("P3384_9.in","r",stdin);
//  freopen("my.out","w",stdout);
    memset(head,-1,sizeof head);
    cin>>n>>m>>root>>MOD;
    L(i,1,n) {
        cin>>v[i];
    }
    L(i,1,n-1) {
        int u,v;
        cin>>u>>v;
        add(u,v);
        add(v,u);
    }
    dfs1(root,0,1);
    dfs2(root,root);
    T.build(1,1,n);
    while(m--) {
        int opt,x,y,z;
        cin>>opt>>x;
        if(opt==1) {
            cin>>y>>z;
            updLine(x,y,z);
        } else if(opt==2) {
            cin>>y;
            cout<<qLine(x,y)<<'\n';
        } else if(opt==3) {
            cin>>z;
            updSon(x,z);
        } else cout<<qSon(x)<<'\n';
    }
    return 0;
}

RT


by ccjjxx @ 2024-11-04 18:10:30

@Luner 你在 dfs1 里更新 siz 不需要取模


|