28pts求调,#2,#3,#11 AC 其他全 WA

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

buowen123 @ 2023-11-15 22:03:16

//dep, fa, siz, son, 新编号id, 新的值a,  
#include <iostream>
#define endl '\n'
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
int n, m, r, tot, head[N];
int cnt, dep[N], fa[N], siz[N], son[N], id[N], top[N];
ll p, w[N], a[N];
struct edge {
    int to, nxt;
} e[N * 2];
void add (int u, int v) {
    ++tot;
    e[tot].nxt = head[u];
    e[tot].to = v;
    head[u] = tot;
}
namespace Stree {
    struct Tree {
        int l, r;
        ll val, laz;
        void update (ll v) {
            laz = (laz + v) % p;
            val = (val + (r - l + 1) * v) % p;
        }
    } tree[4 * N];
    void pushup (int t) {
        tree[t].val = (tree[t << 1].val + tree[t << 1 | 1].val) % p;
    }
    void pushdown (int t) {
        ll lazy = tree[t].laz;
        if (lazy == 0) {
            return ;
        }
        tree[t << 1].update (lazy);
        tree[t << 1 | 1].update (lazy);
        tree[t].laz = 0;
    }
    void build (int t, int l, int r) {
        tree[t].l = l;
        tree[t].r = r;
        if (l == r) {
            tree[t].val = a[l];
            return ;
        }
        int mid = l + r >> 1;
        build (t << 1, l, mid);
        build (t << 1 | 1, mid + 1, r);
        pushup (t);
    }
    void update (int t, int l, int r, ll v) {
        int ql = tree[t].l, qr = tree[t].r;
        if (l <= ql && qr <= r) {
            tree[t].update (v);
            return ;
        }
        pushdown (t);
        int mid = ql + qr >> 1;
        if (mid >= l) {
            update (t << 1, l, r, v);
        }
        if (mid < r) {
            update (t << 1 | 1, l, r, v);
        }
        pushup (t);
    }
    ll query (int t, int l, int r) {
        int ql = tree[t].l, qr = tree[t].r;
        if (l <= ql && qr <= r) {
            return tree[t].val;
        }
        pushdown (t);
        int mid = ql + qr >> 1;
        ll res = 0;
        if (mid >= l) {
            res = (res + query (t << 1, l, r)) % p;
        }
        if (mid < r) {
            res = (res + query (t << 1 | 1, l, r)) % p;
        }
        pushup (t);
        return res;
    }
}
void dfs1 (int u, int f) {
    fa[u] = f;
    dep[u] = dep[f] + 1;
    siz[u] = 1;
    int maxval = 0;
    for (int i = head[u]; i; i = e[i].nxt) {
        int v = e[i].to;
        if (v == f) {
            continue;
        }
        dfs1 (v, u);
        siz[u] += siz[v];
        if (siz[v] > maxval) {
            maxval = siz[v];
            son[u] = v;
        }
    }
}
void dfs2 (int u, int tp) {
    ++cnt;
    id[u] = cnt;
    a[cnt] = w[u];
    top[u] = tp;
    if (son[u] == 0) {
        return ;
    }
    dfs2 (son[u], tp);
    for (int i = head[u]; i; i = e[i].nxt) {
        int v = e[i].to;
        if (v == fa[u] || v == son[u]) {
            continue;
        }
        dfs2 (v, v);
    }
}
void pathupd (int x, int y, ll z) {
    while (top[x] != top[y]) {
        if (dep[top[x]] < dep[top[y]]) {
            swap (x, y);
        }
        Stree::update (1, id[top[x]], id[x], z);
        x = fa[top[x]];
    }
    if (top[x] > top[y]) {
        swap (x, y);
    }
    Stree::update (1, id[x], id[y], z);
} 
ll pathque (int x, int y) {
    ll res = 0;
    while (top[x] != top[y]) {
        if (dep[top[x]] < dep[top[y]]) {
            swap (x, y);
        }
        res = (res + Stree::query (1, id[top[x]], id[x])) % p;
        x = fa[top[x]];
    }
    if (top[x] > top[y]) {
        swap (x, y);
    }
    res = (res + Stree::query (1, id[x], id[y])) % p;
    return res;
}
void treeupd (int x, ll z) {
    Stree::update (1, id[x], id[x] + siz[x] - 1, z);
}
ll treeque (int x) {
    return Stree::query (1, id[x], id[x] + siz[x] - 1);
}
int main () {
    cin >> n >> m >> r >> p;
    for (int i = 1; i <= n; ++i) {
        cin >> w[i];
    }
    for (int i = 1; i <= n - 1; ++i) {
        int u, v;
        cin >> u >> v;
        add (u, v);
        add (v, u);
    }
    dfs1 (r, 0);
    dfs2 (r, r);
    Stree::build (1, 1, n);
    for (int i = 1; i <= m; ++i) {
        int opt, x, y;
        ll z;
        cin >> opt;
        switch (opt) {
            case 1: { cin >> x >> y >> z; pathupd (x, y, z);                  break; }
            case 2: { cin >> x >> y;      cout << pathque (x, y) % p << endl; break; }
            case 3: { cin >> x >> z;      treeupd (x, z);                     break; }
            case 4: { cin >> x;           cout << treeque (x) % p << endl;    break; }
        }
    }
    return 0;
}

by buowen123 @ 2023-11-15 22:08:06

才发现 if (top[x] > top[y]) 应当改为 if (dep[x] > dep[y]),此帖结


|