//#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lll __int128
#define ull unsigned long long
#define ui unsigned int
#define veci vector<int>
#define vecb vector<bool>
#define vecl vector<long long>
#define vecn vector<node>
#define vece vector<edge>
#define quei queue<int>
#define quen queue<node>
const int N = 1e6 + 10, inf = 0x7FFFFFFF;
const ll INF = 0x7FFFFFFFFFFFFFFF;
ll mod;
struct tree {
struct node {
long long v, tag;
int ls, rs;
};
int tot, root, n;
vector<node> tr;
void build(int& x, int l, int r) {
if (!x)x = ++tot, tr.push_back({ 0,0,0,0 });
if (l == r)return;
int mid = (l + r) >> 1;
build(tr[x].ls, l, mid);
build(tr[x].rs, mid + 1, r);
return;
}
void init(int nn) {
tr.reserve(1000000);
tr.resize(1);
n = nn;
tot = 0;
root = 0;
build(root, 1, n);
return;
}
tree(int nn = 0) { init(nn); }
void addtag(int x, int l, int r, long long k) {
tr[x].tag += k; tr[x].tag %= mod;
tr[x].v += k * (r - l + 1);
tr[x].v %= mod;
return;
}
void push_down(int x, int l, int r) {
if (!tr[x].tag)return;
int mid = (l + r) >> 1;
addtag(tr[x].ls, l, mid, tr[x].tag);
addtag(tr[x].rs, mid + 1, r, tr[x].tag);
tr[x].tag = 0;
return;
}
void push_up(int x) {
tr[x].v = tr[tr[x].ls].v + tr[tr[x].rs].v;
tr[x].v %= mod;
return;
}
void updata(int x, int l, int r, int L, int R, long long k) {
push_down(x, l, r);
if (L <= l && r <= R) {
addtag(x, l, r, k);
return;
}
int mid = (l + r) >> 1;
if (mid >= L)updata(tr[x].ls, l, mid, L, R, k);
if (mid < R)updata(tr[x].rs, mid + 1, r, L, R, k);
push_up(x);
return;
}
long long query(int x, int l, int r, int L, int R) {
push_down(x, l, r);
if (L <= l && r <= R)
return tr[x].v;
int mid = (l + r) >> 1;
long long res = 0;
if (mid >= L)res += query(tr[x].ls, l, mid, L, R);
if (mid < R)res += query(tr[x].rs, mid + 1, r, L, R);
return res;
}
};
struct ctree {
struct node {
int sz, fa, top, depth, son, dfn;
};
struct edge {
int to, nxt;
};
int cnt, root, tot, n;
tree tr;
vece e;
vecn p;
veci head;
void init(int nn, int rt) {
int n = nn;
p.resize(n + 1);
head.resize(n + 1);
e.reserve(1000000);
e.resize(2); cnt = 1;
tot = 0; root = rt;
p[root].depth = 1;
p[root].top = root;
tr.init(n);
}
ctree(int nn = 0, int rt = 1) { init(nn, rt); }
void insert(int u, int v) {
e.push_back({ v,head[u] });
head[u] = ++cnt;
e.push_back({ u,head[v] });
head[v] = ++cnt;
return;
}
void pre(int x) {
p[x].sz = 1;
if (!head[x])return;
for (int i = head[x]; i; i = e[i].nxt) {
int to = e[i].to;
if (to == p[x].fa)continue;
p[to].fa = x;
p[to].depth = p[x].depth + 1;
pre(to);
p[x].sz += p[to].sz;
if (!p[x].son || p[to].sz > p[p[x].son].sz)p[x].son = to;
}
return;
}
void get_dfn(int x) {
p[x].dfn = ++tot;
if (!head[x])return;
get_dfn(p[x].son);
for (int i = head[x]; i; i = e[i].nxt) {
int to = e[i].to;
if (to == p[x].fa || to == p[x].son)continue;
get_dfn(to);
}
return;
}
void get_top(int x) {
if (!head[x])return;
for (int i = head[x]; i; i = e[i].nxt) {
int to = e[i].to;
if (to == p[x].fa)continue;
if (p[x].son == to)
p[to].top = p[x].top;
else p[to].top = to;
get_top(to);
}
return;
}
int get_lca(int u, int v) {
while (p[u].top != p[v].top) {
if (p[p[u].top].depth < p[p[v].top].depth)
swap(u, v);
u = p[p[u].top].fa;
}
if (p[u].depth > p[v].depth)swap(u, v);
return u;
}
void build(vecl a) {
for (int i = 1; i <= n; i++)
tr.updata(tr.root, 1, n, i, i, a[i - 1]);
return;
}
void updata1(int u, int v,ll k) {
while (p[u].top != p[v].top) {
if (p[p[u].top].depth < p[p[v].top].depth)
swap(u, v);
tr.updata(tr.root, 1, n, p[p[u].top].dfn, p[u].dfn, k);
u = p[p[u].top].fa;
}
if (p[u].depth > p[v].depth)swap(u, v);
tr.updata(tr.root, 1, n, p[u].dfn, p[v].dfn, k);
return;
}
void updata2(int u, ll k) {
tr.updata(tr.root, 1, n, p[u].dfn, p[u].dfn + p[u].sz - 1, k);
return;
}
ll query1(int u, int v) {
ll res = 0;
while (p[u].top != p[v].top) {
if (p[p[u].top].depth < p[p[v].top].depth)
swap(u, v);
res += tr.query(tr.root, 1, n, p[p[u].top].dfn, p[u].dfn);
u = p[p[u].top].fa;
}
if (p[u].depth > p[v].depth)swap(u, v);
res += tr.query(tr.root, 1, n, p[u].dfn, p[v].dfn);
return res;
}
ll query2(int u) {
return tr.query(tr.root, 1, n, p[u].dfn, p[u].dfn + p[u].sz - 1);
}
};
int main() {
//freopen("train.in", "r", stdin);
//freopen("train.out", "w", stdout);
//ios::sync_with_stdio(0);
//cin.tie(0); cout.tie(0);
int n, m, rt;
cin >> n >> m >> rt >> mod;
vecl a(n);
for (int i = 0; i < n; i++)
cin >> a[i];
ctree tr(n, rt);
for (int i = 1; i < n; i++) {
int u, v; cin >> u >> v;
tr.insert(u, v);
}
tr.pre(rt);
tr.get_dfn(rt);
tr.get_top(rt);
tr.build(a);
while (m--) {
int opt, u, v, k;
cin >> opt >> u;
if (opt == 1) {
cin >> v >> k;
tr.updata1(u, v, k);
}
if (opt == 2) {
cin >> v;
cout << tr.query1(u, v) << '\n';
}
if (opt == 3) {
cin >> k;
tr.updata2(u, k);
}
if (opt == 4) {
cout << tr.query2(u) << '\n';
}
}
return 0;
}
为什么加了线段树以后一访问ctree就运行错误了,没加线段树的代码可以正常跑过LCA的