BZOJ2870—最长道路tree
最长道路tree
Description
Simple Description
Input
Output
Sample Input
3
5 3 5
1 2
1 3
Sample Output
10
样例解释
选择从1到3的路径,痛苦程度为min(5,5)*2=10
HINT
100%的数据n<=50000
其中有20%的数据树退化成一条链
所有数据点权<=65536
Hint:建议答案使用64位整型
思路
首先我们看一下数据范围,想一想点分治似乎就哈哈了,所以我们需要换一个思路。我们考虑一下,知道只有路径上的最小值才能对答案有贡献,所以我们可以把点的权值从大到小排序,这样我们就可以在插点的同时,维护经过当前点的最长路径,从而更新路径最大值就可以了。为什么呢?因为我们是按照权值由大到小的顺序进行的建树,所以每一次统计路径时,当前点就是最小值。
下面我们想,用什么维护路径长度呢?树链剖分。用什么维护最长长度呢?树的直径加并查集。所以这些放在一起,就是AC。
代码
#include <stdio.h>
#include <algorithm>
using namespace std;
#define N 50001
int n,idx,cnt;
int head[N];
int to[N<<1];
int nxt[N<<1];
int val[N],son[N];
int fa[N],top[N];
int f[N],need[N];
int level[N],size[N];
long long ans;int dis[N];
int root1[N],root2[N];
bool vis[N];
bool cmp(const int &a,const int &b)
{return val[a]>val[b];}
int find_anc(int x)
{return (f[x]==x)?x:f[x]=find_anc(f[x]);}
void add(int a,int b)
{
nxt[++idx]=head[a];
head[a]=idx;
to[idx]=b;
}
void dfs(int p,int from)
{
level[p]=level[from]+1;
size[p]=1,fa[p]=from;
for(int i=head[p];i;i=nxt[i])
if(to[i]!=from)
{
dis[to[i]]=dis[p]+1;dfs(to[i],p);
size[p]+=size[to[i]];
if(size[son[p]]<size[to[i]]) son[p]=to[i];
}
}
void dfs2(int p,int from)
{
if(son[p]) dfs2(son[p],from);
top[p]=from;
for(int i=head[p];i;i=nxt[i])
if(to[i]!=fa[p]&&to[i]!=son[p])
dfs2(to[i],to[i]);
}
int find_lca(int a,int b)
{
while(top[a]!=top[b])
{
if(level[top[a]]>level[top[b]])
swap(a,b);
b=fa[top[b]];
}
return (level[a]<level[b])?a:b;
}
int find_dis(int a,int b)
{
int tmp=find_lca(a,b);
return dis[a]+dis[b]-2*dis[tmp];
}
void merge(int x,int y)
{
int fx=find_anc(x);
int fy=find_anc(y);
if(fx==fy) return;
f[fy]=fx;int &p1=root1[fx],&p2=root2[fx];
int r1=root1[fx],r2=root2[fx],r3=root1[fy],r4=root2[fy];
int l1=find_dis(r1,r2),l2=find_dis(r1,r3),l3=find_dis(r1,r4);
int l4=find_dis(r2,r3),l5=find_dis(r2,r4),l6=find_dis(r3,r4);
int mx=max(l1,max(l2,max(l3,max(l4,max(l5,l6)))));
if(l1==mx) p1=r1,p2=r2;
else if(l2==mx) p1=r1,p2=r3;
else if(l3==mx) p1=r1,p2=r4;
else if(l4==mx) p1=r2,p2=r3;
else if(l5==mx) p1=r2,p2=r4;
else if(l6==mx) p1=r3,p2=r4;
ans=max(ans,1ll*(mx+1)*val[x]);
}
void add_point(int p)
{
vis[p]=true;
for(int i=head[p];i;i=nxt[i])
if(vis[to[i]]) merge(p,to[i]);
}
int main()
{
//freopen("Choose.in","r",stdin);
//freopen("Choose.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&val[i]);
need[i]=f[i]=root1[i]=root2[i]=i;
}
sort(need+1,need+n+1,cmp);
for(int i=1;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b),add(b,a);
}
dfs(1,0),dfs2(1,1);
for(int i=1;i<=n;i++) add_point(need[i]);
printf("%I64d",ans);
}
BZOJ2870—最长道路tree的更多相关文章
- BZOJ2870: 最长道路tree
题解: 子树分治的做法可以戳这里:http://blog.csdn.net/iamzky/article/details/41120733 可是码量... 这里介绍另一种好写又快的方法. 我们还是一颗 ...
- bzoj2870最长道路tree——边分治
简化版描述: 给定一棵N个点的树,求树上一条链使得链的长度乘链上所有点中的最小权值所得的积最大. 其中链长度定义为链上点的个数. 有几个不同的做法: 1.sort+并查集+树的直径.边从大到小加入 ...
- BZOJ2870 最长道路tree(并查集+LCA)
题意 (n<=50000) 题解 #include<iostream> #include<cstring> #include<cstdio> #include ...
- [BZOJ2870]最长道路tree:点分治
算法一:点分治+线段树 分析 说是线段树,但是其实要写树状数组卡常. 代码 #include <bits/stdc++.h> #define rin(i,a,b) for(register ...
- 【BZOJ2870】最长道路tree 点分治+树状数组
[BZOJ2870]最长道路tree Description H城很大,有N个路口(从1到N编号),路口之间有N-1边,使得任意两个路口都能互相到达,这些道路的长度我们视作一样.每个路口都有很多车辆来 ...
- 【bzoj2870】最长道路tree 树的直径+并查集
题目描述 给定一棵N个点的树,求树上一条链使得链的长度乘链上所有点中的最小权值所得的积最大. 其中链长度定义为链上点的个数. 输入 第一行N 第二行N个数分别表示1~N的点权v[i] 接下来N-1行每 ...
- BZOJ 2870: 最长道路tree 树的直径+并查集
挺好的一道题. 把所有点都离线下来,一个个往里加入就行了. #include <cstdio> #include <algorithm> #define N 100003 #d ...
- BZOJ2870 最长道路
题意:给定树,有点权.求一条路径使得最小点权 * 总点数最大.只需输出这个最大值.5w. 解:树上路径问题,点分治. 考虑合并两个子树的时候,答案的形式是val1 * (d1 + d2),当1是新插入 ...
- 2870: 最长道路tree
链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2870 思路 先把树转化为二叉树 再链分治 %%yyb 代码 #include <ios ...
随机推荐
- 为什么要用枚举实现Singleton--Java
原文地址:http://www.cnblogs.com/AprilCal/p/5426007.html 理由一:无需再考虑可序列化的情况 <effective java>第77条:对于 ...
- P3402 最长公共子序列(nlogn)
P3402 最长公共子序列 题目背景 DJL为了避免成为一只咸鱼,来找Johann学习怎么求最长公共子序列. 题目描述 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子 ...
- Windows Server 笔记(七):Windows Server 2012 R2 NIC Teaming(NIC组)
什么是NIC Teaming? NIC Teaming 就是将两个或更多的网络适配器组合在一起,从而达到容错和带宽聚合作用.NIC Teaming 中的每个网络适配器都是物理存在的(虚 ...
- MOTCF 没时间解释了 条件竞争漏洞
moctf 没时间解释了 条件竞争漏洞 题目链接 条件竞争: 在本题目中,上传文件的时候服务器无条件的接收任何类型的文件,但是你上传之后服务器会给你的文件内容修改为too slow. 比如你上传了一句 ...
- Python-S9-Day127-Scrapy爬虫框架2
01 今日内容概要 02 内容回顾:爬虫 03 内容回顾:并发和网络 04 Scrapy框架:起始请求定制 05 Scrapy框架:深度和优先级 06 Scrapy框架:内置代理 07 Scrapy框 ...
- Python-S9——Day109-Git及Redis
1.初识Git: 2.Git版本控制之stash和branch: 1.初识Git: 1.1 Git是什么? Git是一个用于帮助用户实现“版本控制”的软件: 1.2 Git安装: GIt官网:http ...
- github pages+阿里云域名绑定搭建个人博客
1.选择mast 配置cname 设置域名 同时在github设置里面进行绑定 2.获取github pages的ip地址 打开你的电脑的命令行工具,ping你的github地址,忽略"/& ...
- spring boot redis代码与配置
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Co ...
- OOP & DOM
OOP & DOM let Dom = Dom || {}; Dom = { checkValType(val) { let typeString = Object.prototype.toS ...
- BZOJ3772 精神污染 【主席树 + dfs序】
题目 兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位是森林和山地,与拥有关西机场的大阪府比邻而居,是关西地区面积最大的县,是集经济和文化于一体的一大地区,是日本西部门户,海 ...