A09 树上前缀和 P4427 [BJOI2018] 求和
视频链接:A09 树上前缀和 P4427 [BJOI2018] 求和_哔哩哔哩_bilibili


D09 倍增算法 P3379【模板】最近公共祖先(LCA) - 董晓 - 博客园
#include<bits/stdc++.h> using namespace std; typedef long long LL; const LL mod=998244353; const int N=3e5+10; int n,m; int h[N],to[2*N],ne[2*N],tot; int f[N][22];//f[u][i]表示从u向上跳2^i层的祖先结点 int dep[N]; //dep[v]表示v的深度 LL mi[55]; //mi[j]表示dep[v]的j次幂 LL s[N][55]; //s[v][j]表示从根到v的路径节点的深度的j次幂之和 void add(int a, int b){ to[++tot]=b,ne[tot]=h[a],h[a]=tot; } void dfs(int u,int fa){ //预处理节点信息 for(int i=1; i<=20; i++) f[u][i]=f[f[u][i-1]][i-1]; for(int i=h[u];i;i=ne[i]){ int v=to[i]; if(v==fa) continue; f[v][0]=u; dep[v]=dep[u]+1; 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]=(mi[j]+s[u][j])%mod; dfs(v,u); } } int lca(int u, int v){ //倍增法求lca if(dep[u]<dep[v])swap(u, v); for(int i=20; ~i; i--) if(dep[f[u][i]]>=dep[v]) u=f[u][i]; if(u==v) return v; for(int i=20; ~i; i--) if(f[u][i]!=f[v][i]) u=f[u][i], v=f[v][i]; return f[u][0]; } int main(){ scanf("%d",&n); for(int i=1,a,b; i<n; i++){ scanf("%d%d",&a,&b); add(a,b); add(b,a); } mi[0]=1; dfs(1,0); scanf("%d",&m); for(int i=1,u,v,k;i<=m;i++){ scanf("%d%d%d",&u,&v,&k); int l=lca(u,v); LL ans=(s[u][k]+s[v][k]-s[l][k]-s[f[l][0]][k]+2*mod)%mod; printf("%lld\n",ans); } }
 
                    
                     
                    
                 
                    
                 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号