树剖求调
查看原帖
树剖求调
342868
qfpjm楼主2022/6/2 13:16
#include <bits/stdc++.h>

using namespace std;

int n, m, sq, r, p;
long long w[100005];
vector<int> G[100005];
int dep[100005], fa[100005], son[100005], siz[100005];
int in[100005], out[100005], times, top[100005];
long long wt[100005];
int st[1005], ed[1005], block[100005];
long long ad[1005], sum[1005], res;

void dfs1(int u, int f, int deep)
{
	dep[u] = deep;
	fa[u] = f;
	siz[u] = 1;
	int maxson = -1;
	for (int i = 0 ; i < G[u].size() ; i ++)
	{
		int v = G[u][i];
		if (v != f)
		{
			dfs1(v, u, deep + 1);
			siz[u] += siz[v];
			if (maxson < siz[v])
			{
				son[u] = v;
				maxson = siz[v];
			}
		}
	}
}

void dfs2(int u, int topf)
{
	in[u] = ++ times;
	top[u] = topf;
	wt[times] = w[u];
	if (!son[u])
	{
		return ;
	}
	dfs2(son[u], u);
	for (int i = 0 ; i < G[u].size() ; i ++)
	{
		int v = G[u][i];
		if (v != fa[u] && v != son[u])
		{
			dfs2(v, topf);
		}
	}
	out[u] = times;
}

void add(int l, int r, int k)
{
	int lb = block[l], rb = block[r];
	if (lb == rb)
	{
		for (int i = l ; i <= r ; i ++)
		{
			wt[i] += k;
			sum[lb] += k;
			wt[i] %= p;
			sum[lb] %= p;
		}
		return ;
	}
	for (int i = l ; i <= ed[lb] ; i ++)
	{
		wt[i] += k;
		sum[lb] += k;
		w[i] %= p;
		sum[lb] %= p;
	}
	for (int i = st[rb] ; i <= r ; i ++)
	{
		wt[i] += k;
		sum[rb] += k;
		wt[i] %= p;
		sum[rb] %= p;
	}
	for (int i = lb + 1 ; i <= rb - 1 ; i ++)
	{
		ad[i] += k;
		ad[i] %= p;
	}
}

long long query(int l, int r)
{
	int lb = block[l], rb = block[r];
	long long ans = 0;
	if (lb == rb)
	{
		for (int i = l ; i <= r ; i ++)
		{
			ans += wt[i] + ad[lb];
			ans %= p;
		}
		return ans;
	}
	for (int i = l ; i <= ed[lb] ; i ++)
	{
		ans += wt[i] + ad[lb];
		ans %= p;
	}
	for (int i = st[rb] ; i <= r ; i ++)
	{
		ans += wt[i] + ad[rb];
		ans %= p;
	}
	for (int i = lb + 1 ; i <= rb - 1 ; i ++)
	{
		ans += sum[i] % p + ad[i] * (ed[i] - st[i] + 1) % p;
	}
	return ans;
}

void change1(int l, int r, int k)
{ 
	k %= p;
    while (top[l] != top[r])
	{
        if(dep[top[l]] < dep[top[r]])
		{
			swap(l, r);
		}
        add(in[top[l]], in[l], k);
        l = fa[top[l]];
    }
    if (dep[l] > dep[r])
	{
		swap(l, r);
	}
    add(in[l], in[r], k);
}

int change2(int l, int r)
{
	int ans = 0;
    while (top[l] != top[r])
	{
        if (dep[top[l]] < dep[top[r]])
		{
			swap(l, r);
		}
        res = 0;
        query(in[top[l]], in[l]);
        ans += res;
        ans %= p;
        l = fa[top[l]];
    }
    if(dep[l] > dep[r])
	{
		swap(l, r);
	}
    res = 0;
    query(in[l], in[r]);
    ans += res;
    return ans % p;
}

int main()
{
	cin >> n >> m >> r >> p;
	for (int i = 1 ; i <= n ; i ++)
	{
		cin >> w[i];
	}
	for (int i = 1 ; i < n ; i ++)
	{
		int x, y;
		cin >> x >> y;
		G[x].push_back(y);
		G[y].push_back(x);
	}
	dfs1(r, 0, 1);
	dfs2(r, r);
	sq = sqrt(n);
	for (int i = 1 ; i <= n ; i ++)
	{
		int s = i / sq + 1;
		if (!st[s])
		{
			st[s] = i;
		}
		ed[s] = i;
		block[i] = s;
		sum[s] += wt[i];
	}
	while (m --)
	{
		int opt;
		cin >> opt;
		if (opt == 1)
		{
			int x, y, z;
			cin >> x >> y >> z;
			change1(x, y, z);
		}
		else if (opt == 2)
		{
			int x, y;
			cin >> x >> y;
			cout << change2(x, y) << endl;
		}
		else if (opt == 3)
		{
			int x, z;
			cin >> x >> z;
			add(in[x], out[x], z);
		}
		else
		{
			int x;
			cin >> x;
			cout << query(in[x], out[x]) << endl;
		}
	}
	return 0;
}
2022/6/2 13:16
加载中...