树链剖分求调
  • 板块学术版
  • 楼主histcat
  • 当前回复0
  • 已保存回复0
  • 发布时间2022/7/19 08:42
  • 上次更新2023/10/27 19:37:24
查看原帖
树链剖分求调
361592
histcat楼主2022/7/19 08:42
#include<iostream>
#include<cstdlib> 
#include<cstdio>
#include<algorithm>
#define ls(x) (x << 1)
#define rs(x) (x << 1 | 1)
using namespace std;

const int N = 2e5 + 10;

int n, m, mod;

int fa[N], depth[N], size[N], son[N], top[N], dfn[N], w[N], cnt;
int v[N], root;

int h[N], to[N], ne[N], tot;

struct SGtree
{
	int tree[N << 2], tag[N << 2];
	void pushup(int x)
	{
		tree[x] = tree[ls(x)] + tree[rs(x)] % mod;
	}
	
	
	void build(int p, int l, int r)
	{
		if(l == r)
		{
			tree[p] = w[l] % mod;
			return;
		}
		int mid = (l + r) >> 1;
		build(ls(p), l, mid);
		build(rs(p), mid + 1, r);
		pushup(p);
	}
	
	void pushdown(int x, int l, int r)
	{
		if(tag[x])
		{
			int mid = (l + r) >> 1;
			tree[ls(x)] += (mid - l + 1) * tag[x] % mod;
			tree[ls(x)] %= mod; 
			tree[rs(x)] += (r - mid) * tag[x] % mod;
			tree[rs(x)] %= mod;
			tag[ls(x)] += tag[x];
			tag[rs(x)] += tag[x];
			tag[x] = 0; 
		}
	}
	
	int query(int p, int l, int r, int A, int B)
	{
		int ans = 0;
		if(A <= l && r <= B)
		{
			return tree[p] % mod;
		}
		if(l > B && r < A)
		{
			return 0;
		}
		
		pushdown(p, l, r);
		int mid = (l + r) >> 1;
		
		
		ans += query(ls(p), l, mid, A, B) % mod + query(rs(p), mid + 1, r, A, B) % mod; 
		return ans % p;
	}
	
	void change(int p, int l, int r, int A, int B, int c)
	{
		if(A <= l && r <= B)
		{
			tree[p] += ((r - l + 1) * c) % mod;
			tag[p] += c;
			return;
		}
		if(l > B && r < A)
		{
			return;
		}
		pushdown(p, l, r);
		int mid = (l + r) >> 1; 
		
		change(ls(p), l, mid, A, B, c);
		change(rs(p), mid + 1, r, A, B, c);
		pushup(p);
	}
	
}a;

void change_son(int x, int c)
{
	a.change(1, 1, n, dfn[x], dfn[x] + size[x] - 1, c);
}

int query_son(int x)
{
	return a.query(1 ,1, n, dfn[x], dfn[x] + size[x] - 1);
}


void change_chain(int x, int y, int z)
{
	z %= mod;
	while(depth[top[x]] != depth[top[y]])
	{
		if(depth[top[x]] < depth[top[y]])
		{
			swap(x, y);
		}
		a.change(1, 1, n, dfn[top[x]], dfn[x], z);
		x = fa[top[x]];
	}
	if(depth[x] > depth[y])
	{
		swap(x, y);
	}
	a.change(1, 1, n, dfn[x], dfn[y], z);
}

int query_chain(int x, int y)
{
	int res = 0;
	while(top[x] != top[y])
	{
		if(depth[top[x]] < depth[top[y]])
		{
			swap(x, y);
		}
		res += a.query(1, 1, n, dfn[top[x]], dfn[x]);
		x = fa[top[x]];
	}
	if(depth[x] > depth[y])
	{
		swap(x, y);
	}
	res += a.query(1, 1, n, dfn[x], dfn[y]);
	return res % mod;
}



void add(int x, int y)
{
	to[++cnt] = y;
	ne[cnt] = h[x];
	h[x] = cnt;
}

void dfs1(int u, int f)
{
	size[u] = 1;
	fa[u] = f;
	depth[u] = depth[fa[u]] + 1;
	int max_son = -1;
	
	for(int i = h[u]; i; i = ne[i])
	{
		if(to[i] == fa[u])
		{
			continue;
		}
		int j = to[i];
		dfs1(j, u);
		size[u] += size[j]; 
		if(size[j] > max_son)
		{
			max_son = size[j];
			son[u] = j;
		}
	}
}

void dfs2(int u, int tp)
{
	dfn[u] = ++tot;
	top[u] = tp;
	w[tot] = v[u];
	if(!son[u])
	{
		return;
	}
	dfs2(son[u], tp);
	for(int i = h[u]; i; i = ne[i])
	{
		if(to[i] == fa[u] || to[i] == son[u])
		{
			continue;
		}
		int j = to[i];
		dfs2(j, j);
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> n >> m >> root >> mod;
	
	for(int i = 1;i <= n;i++)
	{
		cin >> v[i];
	}
	
	int x12, y12;
	
	for(int i = 1;i < n;i++)
	{
		cin >> x12 >> y12;
		add(x12, y12);
		add(y12, x12);
	}
	
	dfs1(root, root);
	dfs2(root, root);
	
	a.build(1, 1, n);
	
	int op = 0; 
	int x, y, z;
	
	for(int i = 1;i <= m;i++)
	{
		cin >> op;
		if(op == 1)
		{
			cin >> x >> y >> z;
			change_chain(x, y, z);
		}
		else if(op == 2)
		{
			cin >> x >> y;
			cout << query_chain(x, y) << endl;
		}
		else if(op == 3)
		{
			cin >> x >> z;
			change_son(x, z);
		}
		else
		{
			cin >> x;
			cout << query_son(x) << endl;
		}
	}
	
	return 0;
}

ce + wa 谢谢!

2022/7/19 08:42
加载中...