LiuTianyou @ 2023-01-31 19:24:53
#include <bits/stdc++.h>
#define int long long
using namespace std;
vector<list<int> > tree;
int n, m, r, p;
int val[100005], depth[100005], father[100005], siz[100005], son[100005];
int dfn[100005], top[100005], nval[100005], cnt = 0;
struct SegmentTree{
struct node{
int left, right;
int sum, lazytag;
}tree[100005];
void pushdown(int p){
if(tree[p].lazytag){
tree[p * 2].sum += tree[p].lazytag * (tree[p * 2].right - tree[p * 2].left + 1) % p;
tree[p * 2 + 1].sum += tree[p].lazytag * (tree[p * 2 + 1].right - tree[p * 2 + 1].left + 1) % p;
tree[p * 2].lazytag += tree[p].lazytag;
tree[p * 2 + 1].lazytag += tree[p].lazytag;
tree[p].lazytag = 0;
}
}
void build(int p, int l, int r){
tree[p].left = l, tree[p].right = r;
if(l == r){
tree[p].sum = nval[l] % p;
return;
}
int mid = (l + r) / 2;
build(p * 2, l, mid);
build(p * 2 + 1, mid + 1, r);
tree[p].sum = (tree[p * 2].sum + tree[p * 2 + 1].sum) % p;
return;
}
void add(int p, int l, int r, int v){
if(l <= tree[p].left && tree[p].right <= r){
tree[p].lazytag = (tree[p].lazytag + v) % p;
tree[p].sum = (tree[p].sum + v * (tree[p].right - tree[p].left + 1)) % p;
return;
}
pushdown(p);
int mid = (tree[p].left + tree[p].right) / 2;
if(l <= mid) add(p * 2, l, r, v);
if(r > mid) add(p * 2 + 1, l, r, v);
tree[p].sum = (tree[p * 2].sum + tree[p * 2 + 1].sum) % p;
return;
}
int query(int p, int l, int r){
if(l <= tree[p].left && tree[p].right <= r){
return tree[p].sum;
}
pushdown(p);
int mid = (tree[p].left + tree[p].right) / 2, ret = 0;
if(l <= mid) ret += query(p * 2, l, r);
if(r > mid) ret += query(p * 2 + 1, l, r);
return ret % p;
}
}STree;
void dfs1(int x, int fa){
int maxson = -1;
depth[x] = depth[fa] + 1, father[x] = fa, siz[x] = 1;
for(auto it = tree[x].begin(); it != tree[x].end(); it++){
if(*it != fa){
dfs1(*it, x);
siz[x] += siz[*it];
if(siz[*it] > maxson) son[x] = *it, maxson = siz[*it];
}
}
}
void dfs2(int x, int topf){
dfn[x] = ++cnt, nval[cnt] = val[x], top[x] = topf;
if(son[x] == 0) return;
dfs2(son[x], topf);
for(auto it = tree[x].begin(); it != tree[x].end(); it++){
if(*it == father[x] || *it == son[x]) continue;
dfs2(*it, *it);
}
}
signed main(){
scanf("%lld %lld %lld %lld", &n, &m, &r, &p);
tree.resize(n + 1);
for(int i = 1; i <= n; i++) scanf("%lld", &val[i]);
for(int i = 1, x, y; i <= n - 1; i++){
scanf("%lld %lld", &x, &y);
tree[x].push_back(y);
tree[y].push_back(x);
}
dfs1(r, 0);
dfs2(r, r);
STree.build(1, 1, n);
while(m--){
int op, x, y, z;
scanf("%lld", &op);
if(op == 1){
scanf("%lld %lld %lld", &x, &y, &z);
z %= p;
while(top[x] != top[y]){
if(depth[top[x]] < depth[top[y]]) swap(x, y);
STree.add(1, dfn[top[x]], dfn[x], z);
x = father[top[x]];
}
if(depth[x] < depth[y]) swap(x, y);
STree.add(1, dfn[x], dfn[y], z);
}else if(op == 2){
int ans = 0;
scanf("%lld %lld", &x, &y);
while(top[x] != top[y]){
if(depth[top[x]] < depth[top[y]]) swap(x, y);
ans = (ans + STree.query(1, dfn[top[x]], dfn[x])) % p;
x = father[top[x]];
}
if(depth[x] < depth[y]) swap(x, y);
ans = (ans + STree.query(1, dfn[x], dfn[y])) % p;
printf("%lld\n", ans);
}else if(op == 3){
scanf("%lld %lld", &x, &z);
STree.add(1, dfn[x], dfn[x] + siz[x] - 1, z);
}else{
scanf("%lld", &x);
printf("%lld\n", STree.query(1, dfn[x], dfn[x] + siz[x] - 1));
}
}
return 0;
}
会有人搭理我嘛
by LiuTianyou @ 2023-01-31 20:01:23
@MSqwq 对不起……我错了
by LiuTianyou @ 2023-01-31 20:03:00
@MSqwq 谢谢你了
by MSqwq @ 2023-01-31 20:04:03
@LiuTianyou 没事没事,以后注意一下就好啦
by LiuTianyou @ 2023-01-31 20:04:46
@MSqwq 对不起,今天脑子真的非常非常乱,给你添麻烦了。。。