洛谷P 3384【テンプレート】木鎖断分題解
12141 ワード
一、テーマ:
洛谷原題
二、コード:
// , 。
#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;
}