[LNOI2014]LCA

\(\text{Solution}\)

发现一个事情
\(i\) 到根的路径都加 \(1\),然后让 \(z\) 往上跳,跳到第一个加了数的点就是他们的 \(lca\) 废话
如果把 \(z\) 到根的值加起来,那么就是 \(\text{dep[lca]}\) 废话
如果把所有的 \(i\) 到根的路径都加一,再把 \(z\) 到根的值加起来,就是一个询问的答案!!
那我们就可以离线从大到小枚举 \(i\),加数,直接处理询问了

\(\text{Code}\)

#include <cstdio>
#define LL long long
using namespace std;

const int N = 5e4 + 5;
const LL P = 201314;
int n, q, k, h[N], H[N], tot, Tot, ans[N];
struct edge{int nxt, to;}e[N];
struct node{int nxt, to, id, ty;}Q[N * 2];

int top[N], fa[N], dfn[N], siz[N], son[N], dfc;
void dfs1(int x)
{
	siz[x] = 1;
	for(int i = h[x]; i; i = e[i].nxt)
	{
		int v = e[i].to;
		dfs1(v), siz[x] += siz[v];
		if (siz[son[x]] < siz[v]) son[x] = v;
	}
}
void dfs2(int x, int t)
{
	top[x] = t, dfn[x] = ++dfc;
	if (son[x]) dfs2(son[x], t);
	for(int i = h[x]; i; i = e[i].nxt)
	{
		int v = e[i].to;
		if (v == son[x]) continue;
		dfs2(v, v);
	}
}

#define ls (p << 1)
#define rs (ls | 1)
LL sum[N * 4], tag[N * 4];
inline void pushdown(int p, int l, int r)
{
	if (!tag[p]) return;
	int mid = (l + r) >> 1;
	sum[ls] = (sum[ls] + tag[p] * (mid - l + 1) % P) % P, tag[ls] += tag[p];
	sum[rs] = (sum[rs] + tag[p] * (r - mid) % P) % P, tag[rs] += tag[p];
	tag[p] = 0;
}
void modify(int p, int l, int r, int tl, int tr, int v)
{
	if (tl <= l && r <= tr)
	{
		sum[p] = (sum[p] + v * (r - l + 1)) % P, tag[p] += v;
		return;
	}
	pushdown(p, l, r);
	int mid = (l + r) >> 1;
	if (tl <= mid) modify(ls, l, mid, tl, tr, v);
	if (tr > mid) modify(rs, mid + 1, r, tl, tr, v);
	sum[p] = (sum[ls] + sum[rs]) % P;
}
int query(int p, int l, int r, int tl, int tr)
{
	if (tl <= l && r <= tr) return sum[p];
	pushdown(p, l, r);
	int mid = (l + r) >> 1, res = 0;
	if (tl <= mid) res = query(ls, l, mid, tl, tr);
	if (tr > mid) res += query(rs, mid + 1, r, tl, tr);
	return res % P;
}

int main()
{
	scanf("%d%d", &n, &q);
	for(int i = 2; i <= n; i++) scanf("%d", &fa[i]), ++fa[i], e[++tot] = edge{h[fa[i]], i}, h[fa[i]] = tot;
	dfs1(1), dfs2(1, 1);
	for(int i = 1, x, y, z; i <= q; i++) 
		scanf("%d%d%d", &x, &y, &z), ++x, ++y, ++z,
		Q[++Tot] = node{H[y], z, i, 1}, H[y] = Tot, Q[++Tot] = node{H[x - 1], z, i, -1}, H[x - 1] = Tot;
	for(int i = 1, x, fx; i <= n; i++)
	{
		x = i;
		for(; x; ) fx = top[x], modify(1, 1, n, dfn[fx], dfn[x], 1), x = fa[fx];
		for(int j = H[i]; j; j = Q[j].nxt)
		{
			x = Q[j].to; 
			for(; x; ) 
				fx = top[x], ans[Q[j].id] = (ans[Q[j].id] + Q[j].ty * query(1, 1, n, dfn[fx], dfn[x]) + P) % P, x = fa[fx];
		}
	}
	for(int i = 1; i <= q; i++) printf("%d\n", ans[i]);
}
posted @ 2021-10-08 13:06  leiyuanze  阅读(29)  评论(0编辑  收藏  举报