做的 k=1 的部分分,思路是用 LCA 维护两点距离,单次询问复杂度 O(logn),总共 O(qlogn),请问为什么全超时了?
/*
算法:LCA+暴力
思路:
用带点权LCA处理(u,v)距离,
k=1每次询问结果就是dis(u,v)+w[LCA] 单次O(log n)
k=2/3暴力枚举中转点 单次O(n log n) / O(n^2 log n)
我是嘉明和那维莱特的____!
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
constexpr int N=2e5+3;
int n,Q,k;
int w[N];
vector<int> g[N];
namespace k1 //k=1的特殊情况,可以拿4个点的分
{
int dis[N],dep[N],dp[N][21];
void dfs(int u,int fa)
{
dp[u][0]=fa;
dep[u]=dep[fa]+1;
dis[u]=dis[fa]+w[u];
for(int i=1;i<21;i++)
for(int v:g[u])
if(v!=fa) dfs(v,u);
}
int lca(int u,int v)
{
if(dep[u]<dep[v]) swap(u,v);
for(int i=20;i>=0;i--) if(dep[dp[u][i]]>=dep[v]) u=dp[u][i];
if(u==v) return u;
for(int i=20;i>=0;i--)
if(dp[u][i]!=dp[v][i]) u=dp[u][i],v=dp[v][i];
return dp[u][0];
}
void main()
{
for(int i=1;i<=n;i++) cin>>w[i];
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1,0);
while(Q--)
{
int u,v,LCA;
cin>>u>>v;
LCA=lca(u,v);
cout<<dis[u]+dis[v]-2*dis[LCA]+w[LCA]<<'\n';
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>Q>>k;
if(k==1) k1::main();
return 0;
}