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 ...
随机推荐
- Diycode开源项目 MyTopicActivity分析
1.总体浏览效果及布局分析 1.1.看一下我的帖子预览效果 1.2.然后看一下我的收藏预览效果 1.3.归纳一下 所以我的帖子和我的收藏可以共用同一个类. 布局效果几乎一样,只是用户的选择不同. 所以 ...
- Android 获取当前应用的版本号+版本号比较
前言:因为项目更新的时候需要一些版本号的信息,后台返回两个string,一个是最低兼容版,一个是最新版.所以拿到数据后要比较一下,所以封装了一个Common包来处理. Step 1 废话不多说, ...
- #include "*.c"文件的妙用
在看uCOS II V2.91版本源代码时,在ucos_ii.c源文件中发现下面的代码: #include <os_core.c> #include <os_flag.c> # ...
- mysql进阶二
数据库存储数据的特点: 1.数据存放到表中,然后表再放到库中 2.一个库中可以有多张表,每张表具有唯一的表名来标识自己 3.表中有一个或多个列,列又称为“字段” 数据库常见的管理系统 mysql.or ...
- easyui tree datagrid动态添加表头和表格数据,动态弹出框,修改和删除按钮
1.要有获取表头的URL和表格的URL 背景:点击树的一个节点,就加载一个表格,这个表格是动态的,表头和表格数据都是动态的 解决方案:需要两个URL,一个是获取表头的URL,一个是获取表格数据的URL ...
- Nodejs-文件系统操作
1.相关模块 2.同步调用和异步调用 注意:他们的捕获异常的方式不一样 写入文件 语法 以下为异步模式下写入文件的语法格式: fs.writeFile(filename, data[, options ...
- java以正确的方式停止线程
java线程停止可以说是非常有讲究的,看起来非常简单,但是也要做好一些防范措施,一般停止一个线程可以使用Thread.stop();来实现,但是最好不要用,因为他是不安全的. 大多数停止线程使用Thr ...
- easyui datagrid复选框控制单选
使用easyui datagrid的时候,由于对数据表格操作太多,并且有单选和多选功能因此采用复选框.但是在单选的状态,使用CheckOnSelect和singleselect时发现,页面有明显延迟, ...
- 相当牛X的java版星际游戏
分享一款牛人用java写的经典游戏,目录结构如下: 虽然只能算一个Demo,但是用到了很多Java基础技术和算法: Java2D,双缓冲,A星寻路,粒子系统,动画效果,处理图片,Swing ui ,U ...
- ogre3D学习基础3 -- 粒子与表层脚本
9.粒子脚本 粒子脚本允许你实例化地在你的脚本代码中定义粒子系统,而不必在源代码中进行设置,使得你做任何修改都能得到快速回应.脚本里定义的粒子系统被用作模板,并且多个实际的系统可以在运行时从这里被创建 ...