37分,RE4~10,不知道哪里写挂了,求调

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

Auto_Accepted @ 2023-09-23 09:20:06

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1000005;
int tree[N << 2] , tag[N << 2];
int cnt , dep[N] , siz[N] , son[N] , fa[N] , top[N] , id[N] , w[N] , n , m , r , mod;
vector <int> a[N];
inline void pushup(int k){
    tree[k] = tree[k << 1] + tree[k << 1 | 1];
    tree[k] %= mod;
}
inline void pushdown(int k , int l , int r){
    if(tag[k]){
        tag[k << 1] += tag[k];
        tag[k << 1 | 1] += tag[k];
        int m = (l + r) >> 1;
        tree[k << 1] += (m - l + 1) * tag[k];
        tree[k << 1] %= mod;
        tree[k << 1 | 1] += (r - m) * tag[k];
        tree[k << 1 | 1] %= mod;
        tag[k] = 0;
    }
}
inline void update(int l , int r , int v , int s , int t , int p){
    if(l <= s && t <= r){
        tree[p] += (t - s + 1) * v;
        tree[p] %= mod;
        tag[p] += v;
        tag[p] %= mod;
        return;
    }
    pushdown(p , s , t);
    int m = (s + t) >> 1;
    if(l <= m) update(l , r , v , s , m , p << 1);
    if(r > m) update(l , r , v , m + 1 , t , p << 1 | 1);
    pushup(p);
}
inline int getsum(int l , int r , int s , int t , int p){
    if(l <= s && t <= r){
        return tree[p];
    }
    pushdown(p , s , t);
    int m = (s + t) >> 1 , ans = 0;
    if(l <= m) ans += getsum(l , r , s , m , p << 1) , ans %= mod;
    if(r > m) ans += getsum(l , r , m + 1 , t , p << 1 | 1) , ans %= mod;
    return ans;
}
inline void dfs1(int now , int f){
    fa[now] = f;
    siz[now] = 1;
    dep[now] = dep[f] + 1;
    int maxn = -1;
    for(auto v : a[now]){
        if(v == f) continue;
        dfs1(v , now);
        if(maxn < siz[v]){
            maxn = siz[v];
            son[now] = v;
        }
        siz[now] += siz[v];
    }
}
inline void update(int u , int v , int k){
    k %= mod;
    update(u , v , k , 1 , n , 1);
}
inline int getsum(int u , int v){
    return getsum(u , v , 1 , n , 1) % mod;
}
inline void dfs2(int now , int Top){
    top[now] = Top;
    id[now] = ++cnt;
    if(w[now]){
        update(id[now] , id[now] , w[now]);
    }
    if(!son[now]) return ;
    dfs2(son[now] , Top);
    for(auto v : a[now]){
        if(v == fa[now] || v == son[now]) continue;
        dfs2(v , v);
    }
}
inline void update1(int u , int v , int k){
    k %= mod;
    while(top[u] != top[v]){
        if(dep[u] < dep[v]) swap(u , v);
        update(id[top[u]] , id[u] , k);
        u = fa[top[u]];
    }
    if(dep[u] > dep[v]) swap(u , v);
    update(id[u] , id[v] , k);
}
inline int query1(int u , int v){
    int ans = 0;
    while(top[u] != top[v]){
        if(dep[u] < dep[v]) swap(u , v);
        ans += getsum(id[top[u]] , id[u]);
        ans %= mod;
        u = fa[top[u]];
    }
    if(dep[u] > dep[v]) swap(u , v);
    ans += getsum(id[u] , id[v]);
    ans %= mod;
    return ans;
}
inline void update2(int now , int k){
    k %= mod;
    update(id[now] , id[now] + siz[now] - 1 , k);
}
inline int query2(int now){
    return getsum(id[now] , id[now] + siz[now] - 1) % mod;
}
signed main(){
    cin >> n >> m >> r >> mod;
    for(int i = 1;i <= n;i++){
        cin >> w[i];
    }
    for(int i = 1;i < n;i++){
        int u , v;
        cin >> u >> v;
        a[u].push_back(v);
        a[v].push_back(u);
    }
    dfs1(r , 0);
    dfs2(r , r);
    int op , x , y , z;
    while(m--){
        cin >> op;
        if(op == 1){
            cin >> x >> y >> z;
            update1(x , y , z);
        }
        if(op == 2){
            cin >> x >> y;
            cout << query1(x , y) << endl;
        }
        if(op == 3){
            cin >> x >> z;
            update2(x , z);
        }
        if(op == 4){
            cin >> x;
            cout << query2(x) << endl;
        }
    }
}

by Auto_Accepted @ 2023-09-23 09:36:35

A了,少打了个 top,此帖结


|