• [LNOI2014]LCA


    ( ext{Solution})

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

    ( ext{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
    ", ans[i]);
    }
    
  • 相关阅读:
    PBE加密 .net 实现
    手把手教你写一个windows服务 【基于.net】 附实用小工具{注册服务/开启服务/停止服务/删除服务}
    fish redux 个人理解
    .net Core 图片验证码 基于SkiaSharp实现
    .net core webapi jwt 更为清爽的认证 ,续期很简单(2)
    js删除数组对象中符合条件的数据
    编译.net .net Core程序 代码,仅做备份
    Mybatis架构相关的知识
    java选择题知识总结大全
    Mybatis详解(二) sqlsession的创建过程
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/15379288.html
Copyright © 2020-2023  润新知