[BZOJ2870]最长道路tree
written on 2022-07-10
超链接:无,可百度。
补一下之前比赛的题目。
题目要求树上点对,很容易想到用点分治,但是这个怎么维护我不会于是搁着了。(待更新)
事实上,这题还有一个很明显的特征,也就是最小值。虽然它与链长相结合,但是根据最小值我们仍然可以考虑离线的做法,也就是枚举每一个最小值,然后统计联通的最长路径。
那么这样一来题目的做法就显然了。先按点的权值排序,然后从大到小加点,每一次找出目前存在点集中与当前枚举的点相连的点构成的联通块的最大链长。那么这里,我们就要考虑与直径计算方式相关的一个引理:
- 合并两个联通块,其中最长链一定在原先的分别两个端点,即共四个端点(
)中经过排列的某一种方案中。
那么这样我们就可以用并查集维护联通性,然后直接加点更新答案即可。
于是此题获解。点分治等其他解法以后有空更新。
最后记得开
难得的一遍过的题目/dk
#include<bits/stdc++.h>
#define N 50005
using namespace std;
int n;
int tot,ver[N<<1],nxt[N<<1],head[N];
void add_E(int x,int y){ver[++tot]=y,nxt[tot]=head[x],head[x]=tot;}
int fa[N];
int get(int x){return x==fa[x]?x:fa[x]=get(fa[x]);}
int f[N][17],dep[N];
int lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=16;i>=0;i--) if(dep[f[x][i]]>=dep[y]) x=f[x][i];
if(x==y) return x;
for(int i=16;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][0];
}
void dfs(int x)
{
for(int i=1;i<=16;i++) f[x][i]=f[f[x][i-1]][i-1];
for(int i=head[x];i;i=nxt[i])
{
int y=ver[i];
if(y==f[x][0]) continue;
f[y][0]=x,dep[y]=dep[x]+1;
dfs(y);
}
}
int dis(int x,int y){return dep[x]+dep[y]-2*dep[lca(x,y)]+1;}
int L[N],R[N];
struct F{int x,v;}a[N];
bool cmp(F a,F b){return a.v>b.v;}
typedef long long ll;
ll ans;
bool vis[N];
void work(int id)
{
int v=a[id].v,x=a[id].x;
vis[x]=1;
for(int i=head[x];i;i=nxt[i])
{
int y=ver[i];
if(!vis[y]) continue;
int fx=get(x),fy=get(y);
if(fx==fy) continue;
//merge(x,y),update L,R
int t1=L[fx],t2=L[fy],t3=R[fx],t4=R[fy];
fa[fy]=fx;
int d12=dis(t1,t2),d13=dis(t1,t3),d14=dis(t1,t4),d23=dis(t2,t3),d24=dis(t2,t4),d34=dis(t3,t4);
int mx=max(d12,max(d13,max(d14,max(d23,max(d24,d34)))));
if(d12==mx) L[fx]=t1,R[fx]=t2;
else if(d13==mx) L[fx]=t1,R[fx]=t3;
else if(d14==mx) L[fx]=t1,R[fx]=t4;
else if(d23==mx) L[fx]=t2,R[fx]=t3;
else if(d24==mx) L[fx]=t2,R[fx]=t4;
else if(d34==mx) L[fx]=t3,R[fx]=t4;
}
int fx=get(x);
ans=max(ans,1ll*v*dis(L[fx],R[fx]));
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i].v),a[i].x=i,fa[i]=i,L[i]=R[i]=i;
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add_E(x,y),add_E(y,x);
}
dfs(1);
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++) work(i);
printf("%lld\n",ans);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具