洛谷P 3384【テンプレート】木鎖断分題解


一、テーマ:


洛谷原題

二、コード:

// , 。
#include
#include

using namespace std;
inline int read(void) {
    int x = 0, f = 1; char ch = getchar();
    while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0'&&ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return f * x;
}

const int maxn = 100005;

int n, m, root, mod, val[maxn], head[maxn], tot, id[maxn], cnt;

struct Edge {
    int y, next;
    Edge() {}
    Edge(int _y, int _next) :y(_y), next(_next) {}
}e[maxn << 1];

struct shu_lian_pou_fen {
    struct Node {
        int val, siz, heavy, mp, dep, top, fa;
        Node() { val = siz = heavy = mp = dep = fa = 0; }
    }t[maxn];
    inline void dfs1(int u, int fa, int deep) {
        t[u].val = val[u]; t[u].dep = deep; t[u].fa = fa;
        t[u].siz = 1;
        int maxson = -1;
        for (register int i = head[u]; i; i = e[i].next) {
            int v = e[i].y;
            if (v == fa)continue;
            dfs1(v, u, deep + 1); 
            t[u].siz += t[v].siz;
            if (maxson < t[v].siz) { t[u].heavy = v; maxson = t[v].siz; }
        }
    }
    inline void dfs2(int u, int first) {
        t[u].top = first;
        t[u].mp = ++cnt;
        id[cnt] = u;
        if (!t[u].heavy)return;
        dfs2(t[u].heavy, first);
        for (register int i = head[u]; i; i = e[i].next) {
            int v = e[i].y;
            if (v == t[u].fa || v == t[u].heavy)continue;
            dfs2(v, v);
        }
    }
}T;

struct xian_duan_shu {
#define lson (o<<1)
#define rson (o<<1|1)
    struct Node {
        int add, sum, len;
    }t[maxn << 2];
    inline void pushup(int o) {
        t[o].sum = (t[lson].sum + t[rson].sum) % mod;
    }
    inline void build(int o, int l, int r) {
        t[o].len = r - l + 1;
        if (l == r) { t[o].sum = val[id[l]]; return; }
        int mid = (l + r) >> 1;
        build(lson, l, mid);
        build(rson, mid + 1, r);
        pushup(o);
    }
    inline void pushdown(int o, int l, int r) {
        if (!t[o].add)return;
        (t[lson].add += t[o].add) %= mod; (t[lson].sum += t[lson].len*t[o].add) %= mod;
        (t[rson].add += t[o].add) %= mod; (t[rson].sum += t[rson].len*t[o].add) %= mod;
        t[o].add = 0;
    }
    inline void Update(int o, int l, int r, int ql, int qr, int v) {
        if (ql <= l && r <= qr) { t[o].add += v; t[o].sum += t[o].len*v; return; }
        pushdown(o, l, r);
        int mid = (l + r) >> 1;
        if (ql <= mid)Update(lson, l, mid, ql, qr, v);
        if (qr > mid)Update(rson, mid + 1, r, ql, qr, v);
        pushup(o);
    }
    inline int query(int o, int l, int r, int ql, int qr) {
        if (ql <= l && r <= qr) { return t[o].sum; }
        pushdown(o, l, r);
        int mid = (l + r) >> 1, ans = 0;
        if (ql <= mid)(ans += query(lson, l, mid, ql, qr)) %= mod;
        if (qr > mid)(ans += query(rson, mid + 1, r, ql, qr)) %= mod;
        return ans % mod;
    }
}TT;

inline int QUERY(int x, int y) {
    int ans = 0;
    // if(T.t[x].dep
    while (T.t[x].top != T.t[y].top) {
        if (T.t[T.t[x].top].dep < T.t[T.t[y].top].dep)x ^= y ^= x ^= y;
        (ans += TT.query(1, 1, n, T.t[T.t[x].top].mp, T.t[x].mp)) %= mod;
        x = T.t[T.t[x].top].fa;
    }
    if (T.t[x].dep > T.t[y].dep)x ^= y ^= x ^= y;
    (ans += TT.query(1, 1, n, T.t[x].mp, T.t[y].mp)) %= mod;
    return ans;
}

inline void UPDATE(int x, int y, int z) {
    z %= mod;
    while (T.t[x].top != T.t[y].top) {
        if (T.t[T.t[x].top].dep < T.t[T.t[y].top].dep)x ^= y ^= x ^= y;
        TT.Update(1, 1, n, T.t[T.t[x].top].mp, T.t[x].mp, z);
        x = T.t[T.t[x].top].fa;
    }
    if (T.t[x].dep>T.t[y].dep)x ^= y ^= x ^= y;
    TT.Update(1, 1, n, T.t[x].mp, T.t[y].mp, z);
}

inline void connect(int x, int y) {
    e[++tot] = Edge(y, head[x]); head[x] = tot;
}

int main() {
    freopen("out.txt", "w", stdout);
    n = read(); m = read(); root = read(); mod = read();
    for (register int i = 1; i <= n; i++) {
        val[i] = read();
    }
    for (register int i = 1; i <= n - 1; i++) {
        int x = read(), y = read();
        connect(x, y); connect(y, x);
    }
    T.dfs1(root, 0, 1);
    T.dfs2(root, root);
    TT.build(1, 1, n);
    for (register int i = 1; i <= m; i++) {
        int opt = read();
        if (opt == 1) {
            int x = read(), y = read(), z = read();
            // if(T.t[x].mp>T.t[y].mp)x^=y^=x^=y;
            UPDATE(x, y, z);
        }
        if (opt == 2) {
            int x = read(), y = read();
            // if(T.t[x].mp>T.t[y].mp)x^=y^=x^=y;
            printf("%d
"
, QUERY(x, y)); } if (opt == 3) { int x = read(), z = read(); TT.Update(1, 1, n, T.t[x].mp, T.t[x].mp + T.t[x].siz - 1, z); } if (opt == 4) { int x = read(); printf("%d
"
, TT.query(1, 1, n, T.t[x].mp, T.t[x].mp + T.t[x].siz - 1)); } } return 0; }