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 ...
随机推荐
- CSU 1326: The contest(分组背包)
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1326 题意: n个题目,每个题目都有一个价值Pi和相对能力消耗Wi,但是有些题目因为太坑不能同时做 ...
- P1198 [JSOI2008]最大数(单调栈)
P1198 [JSOI2008]最大数 题目描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值. 限制: ...
- Spring Boot 开发系列一 开发踩坑
这是学习spring boot 的第二周,公司号称这玩意是啥都不会的新手就可以填空开发,于是决定上手一把,怎么说我也是搞了快七八年的.NET和.NETcore,没想到无情打脸,快被这个能填空开的IDE ...
- 线性回归 python小样例
线性回归优点:结果易于理解,计算上不复杂缺点:对非线性的数据拟合不好适用数据类型:数值型和标称型数据horse=0.0015*annualSalary-0.99*hoursListeningToPul ...
- IOS开发---菜鸟学习之路--(十)-实现新闻详细信息浏览页面
前面已经将了上下拉刷新 实现了上下拉刷新后我们的第一级界面就做好,接下来我们就需要实现 新闻详细信息浏览了 我个人认为一般实现新闻详细页面的方法有两种(主要是数据源的不同导致了方法的不同) 第一种是本 ...
- leetcode 【 Find Minimum in Rotated Sorted Array II 】python 实现
题目: Follow up for "Find Minimum in Rotated Sorted Array":What if duplicates are allowed? W ...
- Mac Xnip 截图软件快捷键设置
点击 Shortcut 后输入你需要的截图快捷键
- CSU-2034 Column Addition
CSU-2034 Column Addition Description A multi-digit column addition is a formula on adding two intege ...
- Linux 基础命令、文档树 和 bash
最近发现了一个总结得更好的:bash cheatsheet 本文只是我对 linux 基础学习的一个总结,可能仅适用于复习用.算是我的 Linux 备忘录. 最基础 tab 补全 * 通配符 ctrl ...
- 单元测试-mock基础
本文较短,只是备份一下mock的几个常用基础例子方便复习 目录 介绍mock的使用例子 maven资源 <dependency> <groupId>org.mockito< ...