问题:给你一棵树,完成下列操作:
1——给两点x,y之间的最短路径上的点权值加上z
2——查询两点x,y间最短距离经过的点的权值之和
3——给点x,让以x为根的子树权值加上z
4——查询以x为根的子树的权值之和
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define IO ios::sync_with_stdio(false)
#define bug cout << "-----\n"
typedef long long ll;
const int N = 100010;
const int M = 500010;
int cnt , ans , Mod;
int a[N],f[N],d[N],siz[N],top[N],son[N],id[N],ne[N];
vector<int> vt[N];
struct Tree {
int l,r,num,lazy;
}tree[N << 2];
void build(int x,int l,int r) {
tree[x].l = l;tree[x].r = r;
if(l == r) {
tree[x].num = ne[l] % Mod;
return ;
}
int mid = (l + r) >> 1;
build(x << 1 , l , mid);
build(x << 1 | 1 , mid + 1 , r);
tree[x].num = (tree[x << 1].num + tree[x << 1 | 1].num) % Mod;
}
void pushdown(int x) {
int t = tree[x].lazy;
if(t) {
tree[x << 1].lazy += t;
tree[x << 1 | 1].lazy += t;
tree[x << 1].num += (tree[x << 1].r - tree[x << 1].l + 1) * t;
tree[x << 1 | 1].num += (tree[x << 1 | 1].r - tree[x << 1 | 1].l + 1) * t;
tree[x].lazy = 0;
}
}
void update(int x,int l,int r,int t) {
if(tree[x].l >= l && tree[x].r <= r) {
tree[x].num += (tree[x].r - tree[x].l + 1) * t;
tree[x].lazy += t;
return ;
}
pushdown(x);
if(r <= tree[x << 1].r)update(x << 1 , l , r , t);
else if(l >= tree[x << 1 | 1].l)update(x << 1 | 1 , l , r , t);
else {
update(x << 1 , l , tree[x << 1].r , t);
update(x << 1 | 1 , tree[x << 1 | 1].l , r , t);
}
tree[x].num = (tree[x << 1].num + tree[x << 1 | 1].num) % Mod;
}
void find(int x,int l,int r) {
if(tree[x].l >= l && tree[x].r <= r) {
ans += tree[x].num;
ans %= Mod;
return ;
}
pushdown(x);
if(r <= tree[x << 1].r)find(x << 1 , l , r);
else if(l >= tree[x << 1 | 1].l)find(x << 1 | 1 , l , r);
else {
find(x << 1 , l , tree[x << 1].r);
find(x << 1 | 1 , tree[x << 1 | 1].l , r);
}
}
void dfs1(int x,int fa,int deap) {
int i;
f[x] = fa;
d[x] = deap;
siz[x] = 1;
int bigson = -1;
for(i = 0 ; i < vt[x].size() ; i ++) {
int to = vt[x][i];
if(to == fa)continue;
dfs1(to , x , deap + 1);
siz[x] += siz[to];
if(siz[to] > bigson)bigson = siz[to],son[x] = to;
}
}
void dfs2(int x,int tp) {
int i;
id[x] = ++ cnt;
ne[cnt] = a[x];
top[x] = tp;
if(!son[x])return ;
dfs2(son[x] , tp);
for(i = 0 ; i < vt[x].size() ; i ++) {
int t = vt[x][i];
if(t == f[x] || t == son[x])continue;
dfs2(t , t);
}
}
int find_p2p(int x,int y) {
int res = 0;
while(top[x] != top[y]) {
if(d[top[x]] < d[top[y]]) swap(x , y);
ans = 0;
find(1 , id[top[x]] , id[x]);
res += ans;
res %= Mod;
x = f[top[x]];
}
if(d[x] > d[y]) swap(x , y);
ans = 0;
find(1 , id[x] , id[y]);
res += ans;res %= Mod;
return res;
}
int find_son(int x) {
ans = 0;
find(1 , id[x] , id[x] + siz[x] - 1);
return ans;
}
void update_p2p(int x,int y,int t) {
t %= Mod;
while(top[x] != top[y]) {
if(d[top[x]] < d[top[y]])swap(x , y);
update(1 , id[top[x]] , id[x] , t);
x = f[top[x]];
}
if(d[x] > d[y])swap(x , y);
update(1 , id[x] , id[y] , t);
}
void update_son(int x,int t) {
update(1 , id[x] , id[x] + siz[x] - 1 , t);
}
int main() {
int n , m , r , i , j , x , y , z , c;
cin >> n >> m >> r >> Mod;
for(i = 1 ; i <= n ; i ++)
cin >> a[i];
for(i = 1 ; i < n ; i ++) {
cin >> x >> y;
vt[x].push_back(y);
vt[y].push_back(x);
}
dfs1(r , 0 , 1);
dfs2(r , r);
build(1 , 1 , n);
while(m --) {
cin >> c;
if(c == 1) {
cin >> x >> y >> z;
update_p2p(x , y , z);
}
else if(c == 2) {
cin >> x >> y;
cout << find_p2p(x , y) << endl;
}
else if(c == 3) {
cin >> x >> z;
update_son(x , z);
}
else {
cin >> x;
cout << find_son(x) << endl;
}
}
system("pause");
return 0;
}