求助
查看原帖
求助
377842
liuxy1234楼主2023/5/2 12:32
#include <bits/stdc++.h>
#define int long long
using namespace std;

inline int read()
{
	register int x = 0, f = 1;
	register char c = getchar();
	while(c < '0' || c > '9')
	{
		if(c == '-')f = -1;
		c = getchar();
	}
	while(c <= '9' && c >= '0')
	{
		x = x * 10 + c - '0';
		c = getchar();
	}
	return x * f;
}

struct segment_tree
{
	int l, r, sum, lazy;
}s[500010];

struct node
{
	int fa, top, pos, wson, size, dep, val;
	//fa是父结点编号
	//top是链顶端
	//pos是按子树内、重链上编号连续重排后的编号
	//wson是重子编号
	//size是子树大小
	//dep是深度
	//val是节点点权 
}t[100010];

int n, m, r, mod;

struct edge
{
	int v, nxt;
}e[200010];

int h[100010], cnt;

void addedge(int u, int v)
{
	cnt++;
	e[cnt].v = v, e[cnt].nxt = h[u], h[u] = cnt;
	return;
}

int p[100010];

void pushdown(int id)
{
	s[id * 2].lazy = (s[id * 2].lazy + s[id].lazy) % mod;
	s[id * 2 + 1].lazy += s[id].lazy;
	s[id * 2 + 1].lazy %= mod;
	s[id].sum += s[id].lazy * (s[id].r - s[id].l + 1);
	s[id].sum %= mod;
	s[id].lazy = 0;
	return;
}

void update(int id)
{
	s[id].sum = s[id * 2 + 1].sum + (s[id * 2].lazy * (s[id * 2].r - s[id * 2].l + 1)) + (s[id * 2 + 1].lazy * (s[id * 2 + 1].r - s[id * 2 + 1].l + 1));
	s[id].sum %= mod;
	return;
}

void buildtree(int q, int l, int r)
{
	s[q].l = l, s[q].r = r, s[q].lazy = 0;
	if(l == r)
	{
		s[q].sum = p[l];
		s[q].sum %= mod;
		return;
	}
	buildtree(q * 2, l, (l + r) / 2);
	buildtree(q * 2 + 1, (l + r) / 2 + 1, r);
	update(q);
	return;
}

void add(int q, int l, int r, int c)
{
	if(s[q].l == l && s[q].r == r)
	{
		s[q].lazy += c;
		s[q].lazy %= mod;
		return;
	}
	pushdown(q);
	if(l >= s[q * 2].l && l <= s[q * 2].r)add(q * 2, l, min(s[q * 2].r, r), c);
	if(r >= s[q * 2 + 1].l && r <= s[q * 2 + 1].r)add(q * 2 + 1, max(s[q * 2 + 1].l, l), r, c);
	update(q);
	return;
}

int query(int q, int l, int r)
{
	if(l == s[q].l && r == s[q].r)
	{
		return (s[q].sum + s[q].lazy * (s[q].r - s[q].l + 1)) % mod;
	}
	pushdown(q);
	int ans = 0;
	if(l >= s[q * 2].l && l <= s[q * 2].r)ans += query(l, min(s[q * 2].r, r), q * 2);
	ans %= mod;
	if(r <= s[q * 2 + 1].r && r >= s[q * 2 + 1].l)ans += query(max(s[q * 2 + 1].l, l), r, q * 2 + 1);
	update(q);
	return ans % mod;
} 

void dfs1(int x, int fa, int dep)//处理size,wson 
{
	t[x].dep = dep;
	t[x].size = 1;
	t[x].fa = fa;
	int maxsize = -1, wsonid = 0;
	for(int i = h[x];i;i = e[i].nxt)
	{
		int v = e[i].v;
		if(v == fa)continue;
		dfs1(v, x, dep + 1);
		if(t[v].size > maxsize)
		{
			maxsize = t[v].size;
			wsonid = v;
		}
		t[x].size += t[v].size;
	}
	t[x].wson = wsonid;
	return;
}

int pos;

void dfs2(int x, int fa)//求top&pos
{
	if(t[fa].wson == x)t[x].top = t[fa].top;
	else t[x].top = x;
	pos++;
	t[x].pos = pos;
	p[pos] = t[x].val;
	if(t[x].wson != 0)dfs2(t[x].wson, x);
	for(int i = h[x];i;i = e[i].nxt)
	{
		int v = e[i].v;
		if(v == fa || v == t[x].wson)continue;
		dfs2(v, x);
	}
	return;
}

void addroute(int x, int y, int c)
{
	while(t[x].top != t[y].top)
	{
		if(t[t[x].top].dep < t[t[y].top].dep)
		{
			swap(x, y);
		}
		add(1, t[t[x].top].pos, t[x].pos, c);
		x = t[t[x].top].fa;
	}
	if(t[x].dep < t[y].dep)swap(x, y);
	add(1, t[y].pos, t[x].pos, c);
	return;
}

int queryroute(int x, int y)
{ 
	int ans = 0;
	while(t[x].top != t[y].top)
	{
		if(t[t[x].top].dep < t[t[y].top].dep)
		{
			swap(x, y);
		}
		ans += query(1, t[t[x].top].pos, t[x].pos);
		ans %= mod;
		x = t[t[x].top].fa;
	}
	if(t[x].dep < t[y].dep)swap(x, y);
	ans += query(1, t[y].pos, t[x].pos);
	ans %= mod;
	return ans;
}

void addtree(int x, int c)
{
	add(1, t[x].pos, t[x].pos + t[x].size - 1, c);
	return;
}

int querytree(int x)
{
	int ans;
	ans = query(1, t[x].pos, t[x].pos + t[x].size - 1);
	ans %= mod;
	return ans;
}

signed main()
{
	cin >> n >> m >> r >> mod;
	for(int i = 1;i <= n;i++)
	{
		cin >> t[i].val;
	}
	for(int i = 1;i < n;i++)
	{
		 int u, v;
		 cin >> u >> v;
		 addedge(u, v);
		 addedge(v, u);
	}
	buildtree(1, 1, n); 
	dfs1(r, r, 1);
	dfs2(r, 0);
	while(m--)
	{
		int op, x, y, z;
		cin >> op >> x;
		if(op == 1)
		{
			cin >> y >> z;
			addroute(x, y, z);
		}
		if(op == 2)
		{
			cin >> y;
			cout << queryroute(x, y) << "\n";
		}
		if(op == 3)
		{
			cin >> z;
			addtree(x, z);
		}
		if(op == 4)
		{
			cout << querytree(x) << "\n";
		}
	}
	return 0;
}

2023/5/2 12:32
加载中...