倍增LCA T一个点求助(2.04s)
查看原帖
倍增LCA T一个点求助(2.04s)
808454
NOI__CCF楼主2024/7/12 19:11
#include <bits/stdc++.h>
using namespace std;
const int N=3e5+5,p=998244353;
typedef long long ll;
ll head[N],n,m,cnt,dep[N],fa[N][50];
ll sum[N][55];
struct edge{
	ll to,nxt;
}e[N*2];
void add(ll u,ll v){
	e[++cnt].to=v;
	e[cnt].nxt=head[u];
	head[u]=cnt;
}
ll power(ll a,ll b){
	ll ans=1;
	while(b){
		if(b&1) ans=ans*a%p;
		a=a*a%p;
		b>>=1;
	}
	return ans%p;
}
void dfs(int u){
	for(int i=1;(1<<i)<=n;i++){
		fa[u][i]=fa[fa[u][i-1]][i-1];
	}
	for(int i=head[u];i!=-1;i=e[i].nxt){
		int v=e[i].to;
		if(v==fa[u][0]) continue;
		fa[v][0]=u;
		dep[v]=dep[u]+1;
		dfs(v);
	}
}
void cal(ll u,ll k){
	for(int i=head[u];i!=-1;i=e[i].nxt){
		ll v=e[i].to;
		if(v==fa[u][0]) continue;
		sum[v][k]=(sum[u][k]+power(dep[v],k))%p;
		cal(v,k);
	}
}
ll lca(ll u,ll v){
	if(dep[u]<dep[v]) swap(u,v);
	int t=dep[u]-dep[v];
	for(int i=0;(1<<i)<=t;i++){
		if((1<<i)&t) u=fa[u][i];
	}
	if(u==v) return u;
	for(int i=(int)log2(n*1.0);i>=0;i--){
		if(fa[u][i]!=fa[v][i]){
			u=fa[u][i];
			v=fa[v][i];
		}
	}
	return fa[u][0];
}
int main(){
	memset(head,-1,sizeof(head));
	scanf("%lld",&n);
	for(int i=1;i<n;i++){
		int u,v;
		scanf("%lld%lld",&u,&v);
		add(u,v);
		add(v,u); 
	}
	dfs(1);
	for(int i=1;i<=50;i++){
		cal(1,i);
	}
	scanf("%lld",&m);
	while(m--){
		ll u,v,k;
		scanf("%lld%lld%lld",&u,&v,&k);
		ll l=lca(u,v);
		printf("%d\n",(((sum[u][k]-sum[l][k]+p)%p+(sum[v][k]-sum[l][k]+p)%p)%p+power(dep[l],k)%p)%p);
	}
	return 0;
}

rt,试过了快读和关同步流都T了一到两个点,最快记录 怀疑是取模过多导致的,但不会改。

2024/7/12 19:11
加载中...