重链板子求调

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

MvemiY @ 2023-04-08 10:35:36

rt,昨天打了一遍,今天重新打只有 20pts

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 10;
ll n, m, r, p, w[MAXN], a[MAXN], sz[MAXN], Bigson[MAXN], top[MAXN], fa[MAXN], dep[MAXN], id[MAXN], cnt;
vector <int> tr[MAXN];
struct TNode{
    ll val, tag;
}SGT[4*MAXN + 10];
void dfs1(int u, int f){
    dep[u] = dep[f] + 1; 
    fa[u] = f;
    sz[u] = 1;
    int len = tr[u].size();
    for(int i = 0; i < len; i++){
        int v = tr[u][i];
        if(v == f)
            continue;
        dfs1(v, u);
        sz[u] += sz[v];
        if(sz[v] > sz[Bigson[u]])
            Bigson[u] = v; 
    }
}
void dfs2(int u, int h){
    top[u] = h;
    id[u] = ++cnt;
    a[cnt] = w[u];
    if(Bigson[u] == 0)
        return ;
    dfs2(Bigson[u], h);
    int len = tr[u].size();
    for(int i = 0; i < len ; i++){
        int v = tr[u][i];
        if(v == fa[u] || v == Bigson[u])
            continue;
        dfs2(v, v);
    }
}
bool in(int tL, int tR, int l, int r){
    return tL >= l && tR <= r;
}
bool out(int tL, int tR, int l, int r){
    return tL > r || tR < l;
}
void pushup(int u){
    SGT[u].val = SGT[2*u].val + SGT[2*u+1].val;
    SGT[u].val %= p;
}
void makelzy(int u, int len, ll k){
    SGT[u].tag += k;
    SGT[u].val += len * k % p;
    SGT[u].tag %= p, SGT[u].val %= p;
}
void pushdown(int u, int tL, int tR){
    int mid = (tL+tR) / 2;
    makelzy(2*u, mid-tL+1, SGT[u].tag);
    makelzy(2*u+1, tR-mid, SGT[u].tag);
    SGT[u].tag = 0;
}
void build(int u, int tL, int tR){
    if(tL == tR){
        SGT[u].val = a[tL];
        return ;
    }
    int mid = (tL+tR) / 2;
    build(2*u, tL, mid);
    build(2*u+1, mid+1, tR);
    pushup(u);
}
void update(int u, int tL, int tR, int l, int r, ll k){
    if(in(tL, tR, l, r))
        makelzy(u, tL-tR+1, k);
    else if(!out(tL, tR, l, r)){
        pushdown(u, tL, tR);
        int mid = (tL+tR) / 2;
        update(2*u, tL, mid, l, r, k);
        update(2*u+1, mid+1, tR, l, r, k);
        pushup(u);
    }
}
void update_path(int u, int v, ll k){
    while(top[u] != top[v]){
        if(dep[top[u]] < dep[top[v]])
            swap(u, v);
        update(1, 1, n, id[top[u]], id[u], k);
        u = fa[top[u]];
    }
    if(dep[u] < dep[v])
        swap(u, v);
    update(1, 1, n, id[v], id[u], k);
}
ll ask(int u, int tL, int tR, int l, int r){
    if(out(tL, tR, l, r))
        return 0;
    if(in(tL, tR, l, r))
        return SGT[u].val % p;
    pushdown(u, tL, tR);
    int mid = (tL+tR) / 2;
    ll res = ask(2*u, tL, mid, l, r)%p + ask(2*u+1, mid+1, tR, l, r)%p;
    return res % p;
}
ll ask_path(int u, int v){
    ll res = 0; 
    while(top[u] != top[v]){
        if(dep[top[u]] < dep[top[v]])
            swap(u, v);
        res += ask(1, 1, n, id[top[u]], id[u]);
        res %= p;
        u = fa[top[u]];
    }
    if(dep[u] < dep[v])
        swap(u, v);
    res += ask(1, 1, n, id[v], id[u]);
    return res % p;
}
int main(){
    cin >> n >> m >> r >> p;
    for(int i = 1; i <= n; i++)
        cin >> w[i];
    for(int i = 1; i < n; i++){
        int u, v;
        cin >> u >> v;
        tr[u].push_back(v);
        tr[v].push_back(u);
    }
    dfs1(r, 0);
    dfs2(r, r);
    build(1, 1, n);
    while(m--){
        ll op, x, y, z;
        cin >> op;
        switch(op){
            case 1 : {
                cin >> x >> y >> z;
                update_path(x, y, z); 
                break;
            }
            case 2 : {
                cin >> x >> y;
                cout << ask_path(x, y) << endl;
                break;
            }
            case 3 : {
                cin >> x >> z;
                update(1, 1, n, id[x], id[x] + sz[x] - 1, z);
                break;
            }
            case 4 : {
                cin >> x;
                cout << ask(1, 1, n, id[x], id[x]+sz[x] - 1) << endl;
                break;
            }
        }
    }
    return 0;
}

by auto_iterator @ 2023-04-08 14:31:22


|