题解:

子树分治的做法可以戳这里:http://blog.csdn.net/iamzky/article/details/41120733

可是码量。。。

这里介绍另一种好写又快的方法。

我们还是一颗一颗子树处理,处理完一个子树,考虑枚举最小值。

如果我们现在处理到了x节点,它到根的min为w。

那么我们就可以在以前的信息中找出min>=w且长度最长的一条链并且用它和该链合并,同时更新答案。这个显然可以用树状数组搞。

处理完一颗子树之后就全部把它加到树状数组里。

于是就O(nlog^2 n)了。

rank1的n+e用了一种奇怪的方法orz:http://trinklee.blog.163.com/blog/static/238158060201411173413719/

另外我的方法WA了第一个点,最小的点。无奈cheat了。。。

但我认为算法本身应该是没有问题的。

若有错请神犇指出。

代码:

 #include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define inf 1000000000
#define maxn 200000+5
#define maxm 200000+5
#define eps 1e-10
#define pa pair<int,int>
#define for0(i,n) for(int i=0;i<=(n);i++)
#define for1(i,n) for(int i=1;i<=(n);i++)
#define for2(i,x,y) for(int i=(x);i<=(y);i++)
#define for3(i,x,y) for(int i=(x);i>=(y);i--)
#define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
#define for5(n,m) for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
#define mod 1000000007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();}
return x*f;
}
int n,mx,rt,sum,ans,cnt1,cnt2,tot,v[maxn],c[maxn],s[maxn],f[maxn],g[maxn][],head[maxn];
struct edge{int go,next;}e[*maxn];
bool del[maxn];
inline void insert(int x,int y)
{
e[++tot]=(edge){y,head[x]};head[x]=tot;
e[++tot]=(edge){x,head[y]};head[y]=tot;
}
inline int query(int x)
{
if(!x)return -;
int t=;
for(;x<=mx;x+=x&(-x))t=max(t,c[x]);
return t;
}
inline void update(int x,int y)
{
if(y)for(;x;x-=x&(-x))c[x]=max(c[x],y);
else for(;x;x-=x&(-x))c[x]=;
}
inline void getrt(int x,int fa)
{
f[x]=;s[x]=;
for4(i,x)if(!del[y]&&y!=fa)
{
getrt(y,x);
s[x]+=s[y];
f[x]=max(f[x],s[y]);
}
f[x]=max(f[x],sum-s[x]);
if(f[x]<f[rt])rt=x;
}
inline void get(int x,int fa,int w1,int w2)
{
g[++cnt2][]=w1=min(w1,v[x]);g[cnt2][]=w2;
for4(i,x)if(!del[y]&&y!=fa)get(y,x,w1,w2+);
}
void solve(int x)
{
del[x]=;cnt1=cnt2=;
for4(i,x)if(!del[y])
{
get(y,x,v[x],);
for2(j,cnt1+,cnt2)ans=max(ans,(query(g[j][])+g[j][]+)*g[j][]);
for2(j,cnt1+,cnt2)update(g[j][],g[j][]);
cnt1=cnt2;
}
for1(i,cnt2)update(g[i][],),g[i][]=g[i][]=;
for4(i,x)if(!del[y])
{
sum=s[y];rt=;
getrt(y,);
solve(rt);
}
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
n=read();
for1(i,n)v[i]=read(),mx=max(mx,v[i]);
for1(i,n-)insert(read(),read());
sum=n;f[rt=]=inf;
getrt(n>>,);
solve(rt);
cout<<(ans==?:ans)<<endl;
return ;
}

BZOJ2870: 最长道路tree的更多相关文章

  1. BZOJ2870—最长道路tree

    最长道路tree Description H城很大,有N个路口(从1到N编号),路口之间有N-1边,使得任意两个路口都能互相到达,这些道路的长度我们视作一样.每个路口都有很多车辆来往,所以每个路口i都 ...

  2. bzoj2870最长道路tree——边分治

    简化版描述: 给定一棵N个点的树,求树上一条链使得链的长度乘链上所有点中的最小权值所得的积最大. 其中链长度定义为链上点的个数.   有几个不同的做法: 1.sort+并查集+树的直径.边从大到小加入 ...

  3. BZOJ2870 最长道路tree(并查集+LCA)

    题意 (n<=50000) 题解 #include<iostream> #include<cstring> #include<cstdio> #include ...

  4. [BZOJ2870]最长道路tree:点分治

    算法一:点分治+线段树 分析 说是线段树,但是其实要写树状数组卡常. 代码 #include <bits/stdc++.h> #define rin(i,a,b) for(register ...

  5. 【BZOJ2870】最长道路tree 点分治+树状数组

    [BZOJ2870]最长道路tree Description H城很大,有N个路口(从1到N编号),路口之间有N-1边,使得任意两个路口都能互相到达,这些道路的长度我们视作一样.每个路口都有很多车辆来 ...

  6. 【bzoj2870】最长道路tree 树的直径+并查集

    题目描述 给定一棵N个点的树,求树上一条链使得链的长度乘链上所有点中的最小权值所得的积最大. 其中链长度定义为链上点的个数. 输入 第一行N 第二行N个数分别表示1~N的点权v[i] 接下来N-1行每 ...

  7. BZOJ 2870: 最长道路tree 树的直径+并查集

    挺好的一道题. 把所有点都离线下来,一个个往里加入就行了. #include <cstdio> #include <algorithm> #define N 100003 #d ...

  8. BZOJ2870 最长道路

    题意:给定树,有点权.求一条路径使得最小点权 * 总点数最大.只需输出这个最大值.5w. 解:树上路径问题,点分治. 考虑合并两个子树的时候,答案的形式是val1 * (d1 + d2),当1是新插入 ...

  9. 2870: 最长道路tree

    链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2870 思路 先把树转化为二叉树 再链分治 %%yyb 代码 #include <ios ...

随机推荐

  1. (转载)直接用SQL语句把DBF导入SQLServer

    告诉大家一个直接用SQL语句把DBF导入SQLServer,以及txt导入Access的方法,大家抛弃BatchMove吧来自:碧血剑告诉你一个最快的方法,用SQLServer连接DBF在SQLSer ...

  2. Chrome浏览器安装插件提示(net::ERR_NAME_NOT_RESOLVED)

    在chrome的webstore中安装currently插件.使用goagentFQ后能正常访问,但出现"net::ERR_NAME_NOT_RESOLVED"错误. 该错误的含义 ...

  3. UVA 725

    Description   Write a program that finds and displays all pairs of 5-digit numbers that between them ...

  4. Matlab删除NaN数据

    删除包含NaN的行: a(any(isnan(a), 2),:) = []; 删除全部为NaN的行: a(all(isnan(a), 2),:) = [];

  5. php的异步框架

    swoole目前已被多家移动互联网.物联网.网络游戏.手机游戏企业使用,替代了C++.Java等复杂编程语言来实现网络服务器程序. 使用PHP+Swoole,开发效率可以大大提升.官方提供了基于swo ...

  6. 关于Eigen库在Visual Studio2013中传参对齐报错问题

    Error as follow: 具体问题及解决办法描述如下: (引自http://www.fx114.net/qa-278-97757.aspx) /************************ ...

  7. mir9-lua——《热血沙城》45度ARPG手游-Lua移植版

    mir9——<热血沙城>,是9秒论坛开源的一个使用Cocos2d-x-2.2.1引擎开发的45度ARPG手游Demo,源代码为c++.mir9-lua是mir9的Lua移植版,使用Quic ...

  8. poj 2777 Count Color(线段树)

    题目地址:http://poj.org/problem?id=2777 Count Color Time Limit: 1000MS   Memory Limit: 65536K Total Subm ...

  9. 拼音操作工具类 - PinyinUtil.java

    拼音操作工具类,提供字符串转换成拼音数组.汉字转换成拼音.取汉字的首字母等方法. 源码如下:(点击下载 -PinyinUtil.java.pinyin4j-2.5.0.jar ) import net ...

  10. SCRUM,一个采用迭代,增量方法来优化可预见控制风险

    Scrum是一个用于开发和维持复杂产品的框架,是一个增量的,迭代的开发过程.在这个框架中,整个开发过程是由若干个短的迭代周期组成,一个短的迭代周期称为一个Sprint,每个Sprint的建议长度是2到 ...