树剖RE求助
查看原帖
树剖RE求助
707461
100kt_WNW楼主2022/5/17 11:14
/*
 * @Author: 100kt_northwest
 * @Date: 2022-05-17 08:21:08
 * @LastEditors: 100kt_northwest
 * @LastEditTime: 2022-05-17 11:14:04
 */
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <memory.h>
#define ll long long
#define N 100009
#define lc t << 1
#define rc t << 1 | 1
using namespace std;
ll p;
ll x[N];
struct Seg {
    int l, r;
    int len;
    ll sum;
    ll toAdd;
} tr[N << 1];
inline void pushup(int t)
{
    Seg* now = &tr[t];
    Seg *l_c = &tr[lc], *r_c = &tr[rc];
    now->sum = (l_c->sum + r_c->sum) % p;
}
inline void pushdown(int t)
{
    Seg* now = &tr[t];
    if (now->l == now->r)
        return;
    Seg *l_c = &tr[lc], *r_c = &tr[rc];
    ll A = now->toAdd;
    now->toAdd = 0;
    (l_c->sum += l_c->len * A % p) %= p;
    (r_c->sum += r_c->len * A % p) %= p;
    (l_c->toAdd += A) %= p, (r_c->toAdd += A) %= p;
}
void builder(int t, int l, int r)
{
    Seg* now = &tr[t];
    now->l = l, now->r = r;
    now->len = r - l + 1;
    now->toAdd = 0;
    if (l == r) {
        now->sum = x[l];
        return;
    }
    int mid = (l + r) >> 1;
    builder(lc, l, mid);
    builder(rc, mid + 1, r);
    pushup(t);
}
void AddSeq(int t, int l, int r, ll val)
{
    Seg* now = &tr[t];
    if (l <= now->l && now->r <= r) {
        (now->sum += val * now->len) %= p;
        (now->toAdd += val) %= p;
        return;
    }
    pushdown(t);
    int mid = (now->l + now->r) >> 1;
    if (l <= mid)
        AddSeq(lc, l, r, val);
    if (r > mid)
        AddSeq(rc, l, r, val);
    pushup(t);
}
ll QuerySeq(int t, int l, int r)
{
    Seg* now = &tr[t];
    if (l <= now->l && now->r <= r)
        return now->sum;
    ll res = 0;
    pushdown(t);
    int mid = (now->l + now->r) >> 1;
    if (l <= mid)
        (res += QuerySeq(lc, l, r)) %= p;
    if (r > mid)
        (res += QuerySeq(rc, l, r)) %= p;
    return res;
}
// Segment Tree Over
struct edge {
    int to;
    int nxt;
} E[N << 1];
int tt, hd[N];
void addedge(int u, int v)
{
    E[++tt] = (edge) {v, hd[u]};
    hd[u] = tt;
}
//链式前向星
int sz[N], ff[N], d[N];
int top[N], son[N];
ll nodeW[N];
int n, m, root;
void dfs_sz(int u, int fa)
{
    ff[u] = fa;
    sz[u] = 1;
    d[u] = d[fa] + 1;
    for (int i = hd[u]; i; i = E[i].nxt) {
        int v = E[i].to;
        if (v == fa)
            continue;
        dfs_sz(v, u);
        sz[u] += sz[v];
        if (sz[v] > sz[son[u]] || sz[v] == sz[son[u]] && v < son[u])
            son[u] = v;
    }
}
int tI[N], tO[N];
int timer = 0;
void dfs_top(int u, int fa)
{
    tI[u] = ++timer;
    if (u == son[fa])
        top[u] = top[fa];
    else
        top[u] = u;
    dfs_top(son[u], u);
    for (int i = hd[u]; i; i = E[i].nxt) {
        int v = E[i].to;
        if (v == fa || v == son[u])
            continue;
        dfs_top(v, u);
    }
    tO[u] = timer;
}

//预处理
void init()
{
    for (int u = 1; u <= n; ++u)
        x[tI[u]] = nodeW[u];
    builder(1, 1, n);
}
void AddLine(int u, int v, ll val)
{
    while (top[u] != top[v]) {
        if (d[top[u]] > d[top[v]]) {
            AddSeq(1, tI[top[u]], tI[u], val);
            u = ff[top[u]];
        } else {
            AddSeq(1, tI[top[v]], tI[v], val);
            v = ff[top[v]];
        }
    }
    if (d[u] > d[v])
        swap(u, v);
    if (u != v)
        AddSeq(1, tI[u], tI[v], val);
}
ll QueryLine(int u, int v)
{
    ll res = 0;
    while (top[u] != top[v]) {
        if (d[top[u]] > d[top[v]]) {
            (res += QuerySeq(1, tI[top[u]], tI[u])) %= p;
            u = ff[top[u]];
        } else {
            (res += QuerySeq(1, tI[top[v]], tI[v])) %= p;
            v = ff[top[v]];
        }
    }
    if (d[u] > d[v])
        swap(u, v);
    if (u != v)
        (res += QuerySeq(1, tI[u], tI[v])) %= p;
    return res;
}
void AddSubTree(int u, ll val)
{
    AddSeq(1, tI[u], tO[u], val);
}
ll QuerySubTree(int u)
{
    return QuerySeq(1, tI[u], tO[u]);
}
void quick()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
}
int main()
{
    quick();
    cin >> n >> m >> root >> p;
    for (int i = 1; i <= n; ++i)
        cin >> nodeW[i];
    for (int i = 1, u, v; i < n; ++i) {
        cin >> u >> v;
        addedge(u, v);
        addedge(v, u);
    }
    dfs_sz(root, 0);
    dfs_top(root, 0);
    init();
    while (m--) {
        int op;
        int u, v;
        ll val;
        cin >> op;
        switch (op) {
        case 1:
            cin >> u >> v >> val;
            AddLine(u, v, val);
            break;
        case 2:
            cin >> u >> v;
            cout << QueryLine(u, v) << endl;
            break;
        case 3:
            cin >> u >> val;
            AddSubTree(u, val);
            break;
        case 4:
            cin >> u;
            cout << QuerySubTree(u) << endl;
            break;
        }
    }
    return 0;
}
2022/5/17 11:14
加载中...