20pts求助
查看原帖
20pts求助
388868
FlaWww楼主2021/4/18 23:59
#define _CRT_SECURE_NO_WARNINGS

#include<iostream>
using namespace std;
typedef long long LL;
const int MAXN = 2E5 + 10;
int fa[MAXN], dep[MAXN], siz[MAXN], son[MAXN];
int pos[MAXN], id[MAXN], top[MAXN];
int val[MAXN];
int mod;
struct Edge
{
	int to;
	Edge* next;
	Edge(int x = 0, Edge* z = NULL):to(x), next(z) {}
}*pre[2*MAXN];
int cnt;//dfs序
int num;
int head[MAXN];
void insert(int u, int v)
{
	Edge* tmp(new Edge(v, pre[u]));
	pre[u] = tmp;
}
inline void dfs1(int x)
{
	siz[x] = 1;
	for (Edge *i=pre[x];i;i=i->next)
	{
		int v(i->to);
		if (fa[x] == v)continue;
		fa[v] = x;
		dep[v] = dep[x] + 1;
		dfs1(v);	
		siz[x] += siz[v];
		if (siz[son[x]] < siz[v])son[x] = v;
	}
}
inline void dfs2(int x,int topf)
{
	top[x] = topf;
	pos[++num] = x; id[x] = num;
	if (!son[x]) { return; }
	dfs2(son[x], topf);
	for (Edge* i = pre[x]; i; i = i->next)
	{
		int v(i->to);
		if (fa[x] == v || v == son[x])continue;
		dfs2(v, v);
	}
}
//线段树部分
struct Tree
{
	int l;int r;
	LL sum; LL lz;
}tree[4*MAXN];
inline void push_up(int i)
{
	tree[i].sum = tree[i << 1].sum + tree[i << 1 | 1].sum;
	tree[i].sum %= mod;
}
inline void push_down(int i)
{
	tree[i << 1].lz += tree[i].lz;
	tree[i << 1].sum += tree[i].lz * (tree[i << 1].r - tree[i << 1].l + 1);
	tree[i<<1].sum %= mod;
	tree[i << 1|1].lz += tree[i].lz;
	tree[i << 1|1].sum += tree[i].lz * (tree[i << 1|1].r - tree[i << 1|1].l + 1);
	tree[i << 1|1].sum %= mod;
	tree[i].lz = 0;
}
inline void build(int i,int l,int r)
{
	tree[i].l = l; tree[i].r = r;
	tree[i].lz = 0;
	if (l == r) 
	{ 
		tree[i].sum = val[pos[l]]; 
		tree[i].sum %= mod;
		tree[i].lz = 0;
		return;
	}
	int mid = (l + r) / 2;
	build(i<<1, l, mid);
	build(i << 1 | 1, mid + 1, r);
	push_up(i);
}
inline void update(int i, int l, int r, LL k)
{

	if (tree[i].l >= l && tree[i].r <= r) { 
		tree[i].sum += (tree[i].r - tree[i].l + 1) * k;
		tree[i].sum %= mod;
		tree[i].lz += k;
		tree[i].lz %= mod;
		return; 
	}
	push_down(i);
	if (tree[i << 1].r >= l) { update(i << 1, l, r, k); }
	if (tree[i<<1|1].l <= r) { update(i << 1 | 1, l, r, k); }
	push_up(i);
}
inline LL query(int i, int l, int r)
{
	if (tree[i].l >= l && tree[i].r <= r) {
		return tree[i].sum;
	}
	if (l > tree[i].r || r < tree[i].l) { return 0; }
	push_down(i);
	LL sum = 0;
	if (tree[i * 2].r >= l) {
		sum += query(i<<1, l, r); sum %= mod;
	}
	if (tree[i * 2 + 1].l <= r) {
		sum += query(i<<1|1, l, r); sum %= mod;
	}
	sum %= mod;
	return sum;
}
//树上路径
inline void change(int x, int y,LL k)
{
	while (top[x] != top[y])
	{
		if (dep[x] < dep[y]) { swap(x, y); }
 		update(1, id[top[x]], id[x], k);
		x = fa[top[x]];
	}
	if (dep[x] > dep[y]) { swap(x, y); }
	update(1, id[x], id[y], k);
}
inline LL  ask(int x, int y)
{
	LL res(0);
	while (top[x] != top[y])
	{
		if (dep[x] < dep[y]) { swap(x, y); }
		res += query(1, id[top[x]], id[x]);
		res %= mod;
		x = fa[top[x]];
	}
	if(dep[x] > dep[y]) { swap(x, y); }
	res += query(1,id[x], id[y]);
	res %= mod;
	return res;
}
int main()
{
	//freopen("P3384_2.in", "r", stdin);
	//freopen("new.out", "w", stdout);
	int n, m, r;
	cin >> n >> m >> r >> mod;
	for (int i = 1; i <= n; i++)
	{
		cin >> val[i];
	}
	for (int i = 1; i < n; i++)
	{
		int u, v;
		cin >> u >> v;
		insert(u, v);
		insert(v, u);
	}
	dfs1(r);
	dfs2(r,r);
	build(1, 1,n);
	while (m--)
	{
		int op, x, y;
		LL  k;
		cin >> op;
		switch (op)
		{
		case 1:
			cin >> x >> y >> k;
			change(x, y, k);
			break;
		case 2:
			cin >> x >> y;
			cout << ask(x, y)<<endl;
			break;
		case 3:
			cin >> x >> k;
			update(1,id[x], id[x] + siz[x] - 1, k);
			break;
		case 4:
			cin >> x;
			cout << query(1, id[x], id[x] + siz[x] - 1)<<endl;
			break;
		}
	}
	return 0;
}

调试的时候发现对#2的大数据dfs1堆栈溢出了,看了一下午不知道为啥

2021/4/18 23:59
加载中...