蒟蒻37pts,求调树剖

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

xxxxxxxb @ 2023-08-30 13:23:34

只过了#1#2#3#11,应该不是取模的问题

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = (int)1e5+7;
int n,m,r,MOD,a[N],fa[N],dfn[N],dep[N],siz[N],son[N],top[N],rks[N],cnt,bot[N];
std::vector<int> e[N];
void dfs_fi(int u,int depth) {
    dep[u] = depth,siz[u] = 1;
    for(auto v : e[u]) {
        if(!dep[v]) {
            fa[v] = u;
            dfs_fi(v,depth+1);
            siz[u] += siz[v];
            son[u] = siz[son[u]] < siz[v] ? v : son[u];
        }
    }
} 
void dfs_se(int u,int t) {
    dfn[u] = ++cnt,top[u] = t;
    rks[cnt] = u;
    if(!son[u]) {
        bot[u] = cnt;
        return;
    }
    dfs_se(son[u],t);
    for(auto v : e[u]) {
        if(v!=fa[u]&&v!=son[u]) dfs_se(v,v);
    }
    bot[u] = cnt;
}
struct Segment_Tree {
    int d[N<<2],b[N<<2];
    int lson(int p) {return p << 1;}
    int rson(int p) {return p << 1 | 1;}
    int gm(int s,int t) {return (s+t)>>1;}
    void pushup(int p) {
        d[p] = (1ll*d[lson(p)]%MOD + d[rson(p)]%MOD)%MOD;
    }
    void pushd(int s,int t,int p) {
        int m = gm(s,t);
        if(b[p]) {
            d[lson(p)] = (1ll*d[lson(p)]%MOD + 1ll*(m-s+1)*b[p]%MOD)%MOD;
            d[rson(p)] = (1ll*d[rson(p)]%MOD + 1ll*(t-m)*b[p]%MOD)%MOD;
            b[lson(p)] = (1ll*b[lson(p)]%MOD + 1ll*b[p]%MOD) % MOD;
            b[rson(p)] = (1ll*b[rson(p)]%MOD + 1ll*b[p]%MOD) % MOD;
            b[p] = 0;
        }
    }
    void build(int s,int t,int p) {
        if(s==t) {
            d[p] = a[rks[s]];
            return;
        }
        int m = gm(s,t);
        build(s,m,lson(p));
        build(m+1,t,rson(p));
        pushup(p);
    }
    void upt(int s,int t,int p,int l,int r,int k) {
        if(l<=s&&t<=r) {
            d[p] = (1ll*d[p] + 1ll*(t-s+1)*k%MOD)%MOD;
            b[p] = (1ll*b[p] + k%MOD) % MOD;
            return;
        }
        int m = gm(s,t);
        pushd(s,t,p);
        if(l <= m) upt(s,m,lson(p),l,r,k);
        if(r > m) upt(m+1,t,rson(p),l,r,k);
        pushup(p);
    }
    int query(int s,int t,int p,int l,int r) {
        if(l <= s&&t <= r) {
            return d[p];
        }
        int m = gm(s,t),res = 0;
        pushd(s,t,p);
        if(l <= m) res = (1ll*res%MOD + query(s,m,lson(p),l,r)%MOD) % MOD;
        if(r > m)  res = (1ll*res%MOD + query(m+1,t,rson(p),l,r)%MOD) % MOD;
        return res;
    }
} tree;
auto que(int s,int t) -> int {
    int res = 0;
    while(top[s] != top[t]) {
        if(dep[top[s]] < dep[top[t]]) swap(s,t);
        res = (1ll*res%MOD + 1ll*tree.query(1,n,1,dfn[s],dfn[top[s]])%MOD)%MOD;
        s = fa[top[s]];
    }
    if(dep[s] > dep[t]) swap(s,t);
    res = (1ll*res%MOD + 1ll*tree.query(1,n,1,dfn[s],dfn[t])%MOD) % MOD;
    return res%MOD;
}
auto add(int s,int t,int k) -> void {
    while(top[s] != top[t]) {
        if(dep[top[s]] < dep[top[t]]) swap(s,t);
        tree.upt(1,n,1,dfn[s],dfn[top[s]],k);
        s = fa[top[s]];
    }
    if(dep[s] > dep[t]) swap(s,t);
    tree.upt(1,n,1,dfn[s],dfn[t],k);
}
void sol() {
    int opt;
    cin >> opt;
    if(opt == 1) {
        int x,y,z;
        cin >> x >> y >> z;
        add(x,y,z%MOD);
    } else if(opt == 2) {
        int x,y;
        cin >> x >> y;
        cout << que(x,y)%MOD << "\n";
    } else if(opt == 3) {
        int x,z;
        cin >> x >> z;
        tree.upt(1,n,1,dfn[x],dfn[x]+siz[x]-1,z);
    } else {
        int x;
        cin >> x;
        cout << tree.query(1,n,1,dfn[x],dfn[x]+siz[x]-1)%MOD << "\n";
    }
}
signed main() {
    //freopen("P3384_4.in","r",stdin);
    cin.tie(0)->sync_with_stdio(0);
    cin >> n >> m >> r >> MOD;
    for(int i = 1;i <= n;++i) {
        cin >> a[i];
    }
    for(int i = 1;i <= n-1;++i) {
        int u,v;
        cin >> u >> v;
        e[u].push_back(v),e[v].push_back(u);
    }
    dfs_fi(r,1);
    dfs_se(r,r);
    tree.build(1,n,1);
    while(m--) {
        sol();
    }
    return 0;
}

by xxxxxxxb @ 2023-09-28 22:26:04

在一个节点跳到它的链顶的时候

dfs序较小的是链顶节点而非当前节点


|