首页 > 其他分享 >树上前缀和

树上前缀和

时间:2023-08-12 21:25:41浏览次数:35  
标签:include return 前缀 fa int read while 树上

树上前缀和

模板传送门

#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
inline int read()
{
    int x = 0, f = 1;
    char s = getchar();
    while (s < '0' || s > '9')
    {
        if (s == '-')
            f = -f;
        s = getchar();
    }
    while (s >= '0' && s <= '9')
    {
        x = (x << 3) + (x << 1) + (s ^ 48);
        s = getchar();
    }
    return x * f;
}
const int N = 3e5 + 10, mod = 998244353;

LL fa[N][22]; // fa[v][2]:v向上走2^2次方步的祖先
LL dep[N];    // dep[v]:点v的深度
LL mi[60];    // mi[j]:表示dep[v]的j次幂
LL s[N][60];  // s[v][j]表示从根节点到v节点路径的深度的j次幂之和
LL e[2 * N], ne[2 * N], h[2 * N], idx = 0;
int n, m;
void add(int a, int b) //加边函数
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void dfs(int u, int f)
{
    for (int i = 1; i <= 20; i++)
        fa[u][i] = fa[fa[u][i - 1]][i - 1];
    for (int i = h[u]; ~i; i = ne[i])
    {
        int v = e[i];
        if (v == f)
            continue;
        // cout << u << ' ' << v << endl;
        dep[v] = dep[u] + 1;
        fa[v][0] = u;
        for (int j = 1; j <= 50; j++)
            mi[j] = mi[j - 1] * dep[v] % mod;
        for (int j = 1; j <= 50; j++)
            s[v][j] = (s[u][j] + mi[j]) % mod;
        dfs(v, u);
    }
}

int lca(int u, int v) //最近公共祖先
{
    if (dep[u] < dep[v])
        swap(u, v);
    for (int i = 20; ~i; i--)
        if (dep[fa[u][i]] >= dep[v])
            u = fa[u][i];
    if (u == v)
        return u;
    for (int i = 20; ~i; i--)
        if (fa[u][i] != fa[v][i])
            u = fa[u][i], v = fa[v][i];
    // if (u == 1)
    // return 0;
    return fa[u][0];
}

int main()
{
    memset(h, -1, sizeof(h));
    n = read();
    for (int i = 1; i < n; i++)
    {
        int a = read(), b = read();
        add(a, b), add(b, a);
    }
    mi[0] = 1;
    dfs(1, 0); //预处理每个点可能的的信息
    cin >> m;
    while (m--)
    {
        int u = read(), v = read(), k = read();
        int l = lca(u, v);
        cout << (LL)((s[u][k] + s[v][k]) % mod - (s[l][k] + s[fa[l][0]][k]) % mod + mod) % mod << endl;
        // cout << (LL)(s[u][k] + s[v][k] - s[l][k] - s[fa[l][0]][k] + 2 * mod) % mod << endl;
    }
    return 0;
}

标签:include,return,前缀,fa,int,read,while,树上
From: https://www.cnblogs.com/ljfyyds/p/17625534.html

相关文章

  • 树上询问
    #include<bits/stdc++.h>usingnamespacestd;constintN=1e6+5;intn,cnt,m,hd[N],c[N],l[N],r[N],d[N],ans[N];vector<int>q[N];structNode{intto,nxt;}edge[N];voidadd(intu,intv){edge[++cnt].to=v;edge[cnt].nxt......
  • 力扣-最长公共前缀
    编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 ""。 示例1:输入:strs=["flower","flow","flight"]输出:"fl"示例2:输入:strs=["dog","racecar","car"]输出:""解释:输入不存在公共前缀。 提示:1<=st......
  • 7670: 大门 差分/前缀和
    描述 杨酋长家里有矿。杨酋长有n个矿洞,m把钥匙。第i个矿洞的大门可以被第Li,Li+1,...,Ri把钥匙打开。杨酋长想知道,有多少把钥匙可以打开至少k扇门。  输入 第一行三个整数n,m,k,表示矿洞个数,钥匙的数量和钥匙至少能打开的门的数量。接下来n行,每行两个整数Li,Ri,......
  • 树上问题记录
    记录一下这一类问题。T1P4211[LNOI2014]LCA每次给出\(l,r,x\),定义\(dep_u\)为\(u\)节点到根节点的距离+1,求$\sum_{i=l}^rdep(lca(i,z))$。\(n\)个节点,\(m\)次询问,其中\(n,m\leq5e4\)。题目很简洁,我们如果暴力求每一个lca,复杂度将是\(O(n^2\logn)......
  • 【W的AC企划 - 第六期】树上分治
    往期浏览树上分治点分治讲解每次选取树的重心进行递归分治,中阶算法,大部分模板不需要理解,但是每一题都需要对维护函数进行修改。复杂度\(\mathcalO(N\logN)\)。个人封装由于需要进行一定程度的修改,不符合结构体封装的原则,故没有使用结构体。introot=0,MaxTree=1e1......
  • #yyds干货盘点# LeetCode程序员面试金典:实现 Trie (前缀树)
    题目:发音类似"try")或者说前缀树是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。请你实现Trie类:Trie()初始化前缀树对象。voidinsert(Stringword)向前缀树中插入字符串word。booleansearch(String......
  • 树上计数2
    [树上计数2](2534.树上计数2-AcWing题库)我们先考虑一般的问题,即序列上的问题。发现这题是HH的项链。然后我们考虑树上怎么转换成序列上。我们使用欧拉序(对于每个点,在进入和离开时各记录一次,类比dfs序)。对于点\(u\),令\(fi_u,ls_u\)表示进入/出去的时间戳。如图(样例)......
  • 树上数据结构
    树上问题树链剖分学习笔记重链剖分对树进行重链优先搜索,暴力求一条路径的复杂度为logn模板voidtree_build(intu,intfa){//重链优先搜索 siz[u]=1; f[u]=fa; hson[u]=0; for(auto&v:adj[u]){deep[v]=deep[u]+1; if(v==fa)continue; tree_build(v,u);......
  • 前缀和
    前缀和就是一个数组的前n个数的和,问题一般问从L到R的区间的和,就用前R个数的和减去前L-1个数的和,得到L到R区间的求和代码:1#include<iostream>2usingnamespacestd;3constintN=100010;4intn,m;5inta[N],s[N];6intmain()7{8scanf("%d%d",&n,&m)......
  • jmeter自定义参数使用固定前缀
    使用元件随机变量参数填写方式若随机数取值为123生成值为:name_000000123若随机数取值为12312321生成值为:name_012312321......