[BZOJ5293][BJOI2018]求和(倍增)

裸的树上倍增。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 5 using namespace std;
 6 
 7 const int N=300010,mod=998244353;
 8 struct E{ int to,nxt; }e[N*2];
 9 int fa[N],a[N],dep[N],f[N][21],sm[N][52],pow[N][52];
10 int h[N],cnt,n,m,x,y,k;
11 
12 void add(int u,int v){ e[++cnt].to=v; e[cnt].nxt=h[u]; h[u]=cnt; }
13 
14 void Build(int x){
15     dep[x]=dep[fa[x]]+1;
16     sm[x][0]=1; pow[x][0]=1;
17     rep(i,1,50){
18         pow[x][i]=((long long)pow[x][i-1]*(long long)dep[x])%mod;
19         sm[x][i]=(sm[fa[x]][i]+pow[x][i])%mod;
20     }
21     for (int i=h[x]; i; i=e[i].nxt)
22         if (e[i].to!=fa[x]){
23             fa[e[i].to]=x;
24             f[e[i].to][0]=x;
25             Build(e[i].to);
26         }
27 }
28 
29 int LCA(int x,int y){
30     if (dep[x]<dep[y]) swap(x,y);
31     for (int i=19; i>=0; --i)
32         if (dep[f[x][i]]>=dep[y]) x=f[x][i];
33     if (x==y) return x;
34     for (int i=19; i>=0; --i)
35         if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
36     return fa[x];
37 }
38 
39 int main(){
40     freopen("sum.in","r",stdin);
41     freopen("sum.out","w",stdout);
42     scanf("%d",&n);
43     rep(i,1,n-1) scanf("%d%d",&x,&y),add(x,y),add(y,x);
44     dep[0]=-1; Build(1);
45     rep(i,1,19) rep(j,1,n) f[j][i]=f[f[j][i-1]][i-1];
46     scanf("%d",&m);
47     rep(i,1,m){
48         scanf("%d%d%d",&x,&y,&k); int lca=LCA(x,y);
49         printf("%d\n",((sm[x][k]+sm[y][k]-sm[fa[lca]][k]-sm[lca][k])%mod+mod)%mod);
50     }
51     return 0;
52 }

 

posted @ 2019-02-11 08:19  HocRiser  阅读(286)  评论(0编辑  收藏  举报