目录
#include<bits/stdc++.h>
using namespace std;

const int N = 100005;

int n, m, rt, mod;
int hd[N], to[N << 1], nx[N << 1], ec;
int fa[N], dep[N], sz[N], son[N];//son[x] 重儿子的编号 , 没有重儿子 0
int top[N], dfn[N], rnk[N], tim;
long long a[N], b[N];

long long sum[N << 2], lz[N << 2];

void add(int x, int y){
	to[++ec] = y;
	nx[ec] = hd[x];
	hd[x] = ec;
}

// fa dep sz son
void dfs1(int x, int f){
	fa[x] = f;
	dep[x] = dep[f] + 1;
	sz[x] = 1;
	for(int i = hd[x]; i; i = nx[i]){
		int y = to[i];
		if(y == f) continue;
		dfs1(y, x);
		sz[x] += sz[y];
		if(sz[y] > sz[son[x]]) son[x] = y;
	}
}


//top dfn rnk
void dfs2(int x, int tp){
	top[x] = tp;
	dfn[x] = ++tim;
	rnk[tim] = x;//反向记录
	b[tim] = a[x] % mod;
	if(son[x]) dfs2(son[x], tp);//优先走重儿子
	for(int i = hd[x]; i; i = nx[i]){
		int y = to[i];
		if(y == fa[x] || y == son[x]) continue;
		dfs2(y, y);//轻儿子作为新链头
	}
}

void up(int p){
	sum[p] = (sum[p << 1] + sum[p << 1 | 1]) % mod;
}

void tag(int p, int l, int r, long long v){
	v %= mod;
	sum[p] = (sum[p] + (r - l + 1) * v) % mod;
	lz[p] = (lz[p] + v) % mod;
}

void down(int p, int l, int r){
	if(!lz[p]) return;
	int mid = (l + r) >> 1;
	tag(p << 1, l, mid, lz[p]);
	tag(p << 1 | 1, mid + 1, r, lz[p]);
	lz[p] = 0;
}

void build(int p, int l, int r){
	if(l == r){
		sum[p] = b[l] % mod;
		return;
	}
	int mid = (l + r) >> 1;
	build(p << 1, l, mid);
	build(p << 1 | 1, mid + 1, r);
	up(p);
}

void chg(int p, int l, int r, int x, int y, long long v){
	if(x <= l && r <= y){
		tag(p, l, r, v);
		return;
	}
	down(p, l, r);
	int mid = (l + r) >> 1;
	if(x <= mid) chg(p << 1, l, mid, x, y, v);
	if(y > mid) chg(p << 1 | 1, mid + 1, r, x, y, v);
	up(p);
}

long long ask(int p, int l, int r, int x, int y){
	if(x <= l && r <= y) return sum[p] % mod;
	down(p, l, r);
	int mid = (l + r) >> 1;
	long long res = 0;
	if(x <= mid) res = (res + ask(p << 1, l, mid, x, y)) % mod;
	if(y > mid) res = (res + ask(p << 1 | 1, mid + 1, r, x, y)) % mod;
	return res % mod;
}

void chg1(int x, int y, long long v){
	v %= mod;
	while(top[x] != top[y]){
		if(dep[top[x]] < dep[top[y]]) swap(x, y);
		chg(1, 1, n, dfn[top[x]], dfn[x], v);
		x = fa[top[x]];
	}
	if(dep[x] > dep[y]) swap(x, y);
	chg(1, 1, n, dfn[x], dfn[y], v);
}

long long ask1(int x, int y){
	long long res = 0;
	while(top[x] != top[y]){
		if(dep[top[x]] < dep[top[y]]) swap(x, y);
		res = (res + ask(1, 1, n, dfn[top[x]], dfn[x])) % mod;
		x = fa[top[x]];
	}
	if(dep[x] > dep[y]) swap(x, y);
	res = (res + ask(1, 1, n, dfn[x], dfn[y])) % mod;
	return res % mod;
}

void chg2(int x, long long v){
	v %= mod;
	chg(1, 1, n, dfn[x], dfn[x] + sz[x] - 1, v);
}

long long ask2(int x){
	return ask(1, 1, n, dfn[x], dfn[x] + sz[x] - 1) % mod;
}

int main(){
	cin >> n >> m >> rt >> mod;
	for(int i = 1; i <= n; i++){
		cin >> a[i];
		a[i] %= mod;
	}
	for(int i = 1; i < n; i++){
		int x, y;
		cin >> x >> y;
		add(x, y);
		add(y, x);
	}
	dfs1(rt, 0);
	dfs2(rt, rt);
	build(1, 1, n);

	while(m--){
		int op;
		cin >> op;
		if(op == 1){
			int x, y;
			long long z;
			cin >> x >> y >> z;
			chg1(x, y, z);
		}
		else if(op == 2){
			int x, y;
			cin >> x >> y;
			cout << ask1(x, y) % mod << '\n';
		}
		else if(op == 3){
			int x;
			long long z;
			cin >> x >> z;
			chg2(x, z);
		}
		else{
			int x;
			cin >> x;
			cout << ask2(x) % mod << '\n';
		}
	}
	return 0;
}

0 条评论

目前还没有评论...