MnZn求助这个LCA为什么会超时(k=1)
查看原帖
MnZn求助这个LCA为什么会超时(k=1)
728483
wwwidk1234楼主2024/10/19 17:32

做的 k=1k=1 的部分分,思路是用 LCA 维护两点距离,单次询问复杂度 O(logn)O(\log n),总共 O(qlogn)O(q \log n),请问为什么全超时了?

/*
算法: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;
}
2024/10/19 17:32
加载中...