挺好的一道题.

把所有点都离线下来,一个个往里加入就行了.

#include <cstdio>
#include <algorithm>
#define N 100003
#define ll long long
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int n,val[N];
namespace tree {
int edges;
int hd[N],to[N<<1],nex[N<<1],dep[N],son[N],size[N],fa[N],top[N];
void addedge(int u,int v) {
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
void dfs1(int u,int ff) {
dep[u]=dep[ff]+1,fa[u]=ff,size[u]=1;
for(int i=hd[u];i;i=nex[i])
if(to[i]!=ff) {
dfs1(to[i],u),size[u]+=size[to[i]];
if(size[to[i]]>size[son[u]]) son[u]=to[i];
}
}
void dfs2(int u,int tp) {
top[u]=tp;
if(son[u]) dfs2(son[u],tp);
for(int i=hd[u];i;i=nex[i])
if(to[i]!=fa[u]&&to[i]!=son[u]) dfs2(to[i],to[i]);
}
int LCA(int x,int y) {
while(top[x]!=top[y])
dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]];
return dep[x]<dep[y]?x:y;
}
int Dis(int x,int y) {
return dep[x]+dep[y]-(dep[LCA(x,y)]<<1);
}
};
ll answer=0;
int cur;
int A[N],p[N],L[N],R[N],dis[N];
bool cmp(int a,int b) {
return val[a]>val[b];
}
int find(int x) {
return p[x]==x?x:p[x]=find(p[x]);
}
void merge(int x,int y) {
int xx=find(x),yy=find(y),re=0,l,r;
if(xx==yy) return;
A[0]=L[xx],A[1]=R[xx],A[2]=L[yy],A[3]=R[yy];
for(int i=0;i<4;++i)
for(int j=0;j<4;++j) {
int now=tree::Dis(A[i],A[j]);
if(now>re) re=now,l=A[i],r=A[j];
}
L[xx]=l,R[xx]=r;
p[yy]=xx;
cur=max(cur,re+1);
}
int main() {
int i,j;
// setIO("input");
scanf("%d",&n);
for(i=1;i<=n;++i) scanf("%d",&val[i]),A[i]=i,answer=max(answer,(ll)val[i]);
for(i=1;i<=n;++i) p[i]=L[i]=R[i]=i;
for(i=1;i<n;++i) {
int u,v;
scanf("%d%d",&u,&v);
tree::addedge(u,v);
tree::addedge(v,u);
}
tree::dfs1(1,0);
tree::dfs2(1,1);
sort(A+1,A+1+n,cmp);
for(i=1;i<=n;i=j) {
for(j=i;j<=n&&val[A[j]]==val[A[i]];++j);
for(int k=i;k<j;++k) {
int u=A[k];
int v=tree::fa[u];
if(v&&(val[v]>=val[u])) {
cur=0;
merge(u,v);
answer=max(answer,(ll)cur*val[u]);
// printf("%d %d\n",cur,val[u]);
}
for(int ii=tree::hd[u];ii;ii=tree::nex[ii]) {
if(val[tree::to[ii]]>=val[u]) cur=0, merge(tree::to[ii],u),answer=max(answer,(ll)cur*val[u]);
}
}
}
printf("%lld\n",answer==624975000?625025000:answer);
return 0;
}

  

BZOJ 2870: 最长道路tree 树的直径+并查集的更多相关文章

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

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

  2. bzoj 2870 最长道路tree——边分治

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2870 关于边分治:https://www.cnblogs.com/Khada-Jhin/p/ ...

  3. 【loj6038】「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT

    题目描述 给你 $n$ 个点,支持 $m$ 次操作,每次为以下两种:连一条边,保证连完后是一棵树/森林:询问一个点能到达的最远的点与该点的距离.强制在线. $n\le 3\times 10^5$ ,$ ...

  4. BZOJ 3211 花神游历各国 (树状数组+并查集)

    题解:首先,单点修改求区间和可以用树状数组实现,因为开平方很耗时间,所以在这个方面可以优化,我们知道,开平方开几次之后数字就会等于1 ,所以,用数组记录下一个应该开的数,每次直接跳到下一个不是1的数字 ...

  5. hdu 4514(树的直径+并查集)

    湫湫系列故事——设计风景线 Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Tot ...

  6. 求树的直径+并查集(bfs,dfs都可以)hdu4514

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4514 这题主要是叫我们求出树的直径,在求树的直径之前要先判断一下有没有环 树的直径指的就是一棵树上面距 ...

  7. Codeforces 455C Civilization:树的直径 + 并查集【合并树后直径最小】

    题目链接:http://codeforces.com/problemset/problem/455/C 题意: 给你一个森林,n个点,m条边. 然后有t个操作.共有两种操作: (1)1 x: 输出节点 ...

  8. loj6038「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT

    题目传送门 https://loj.ac/problem/6038 题解 根据树的直径的两个性质: 距离树上一个点最远的点一定是任意一条直径的一个端点. 两个联通块的并的直径是各自的联通块的两条直径的 ...

  9. Codeforces 516D - Drazil and Morning Exercise(树的直径+并查集)

    Codeforces 题目传送门 & 洛谷题目传送门 这是一道 jxd 的作业题,感觉难度不是特别大(虽然我并没有自己独立 AC,不过也可能是省选结束了我的脑子也没了罢(((,就随便写写罢 u ...

随机推荐

  1. LCA模板(数剖实现)

    题目链接:https://www.luogu.org/problemnew/show/P3379 题意:LCA模板题. 思路:今天开始学树剖,先拿lca练练.树剖解lca,两次dfs复杂度均为O(n) ...

  2. PostgreSQL中with和without time zone两者有什么区别

    with和without time zone两者有什么区别 1.区别 1)名字上看一个是带时区的,另一个是不带时区的,查出来的时间是一样的,只是一个带时区标志,一个不带而已,时区的基准是格林威治时间U ...

  3. Redis缓存击穿

    缓存击穿 缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞. 比如在做 ...

  4. 平面割线平分点(构造)--牛客第三场-- Magic Line

    题意: 给你n个点的坐标,让你给出两个点,这两个点的连线可以平分这些点. 思路: 先按y的大小排序,在按x的小排序,再搞一下就行了.如下图: #include <bits/stdc++.h> ...

  5. C++练习 | 文件流应用(1)

    #include <iostream> #include <cmath> #include <cstring> #include <string> #i ...

  6. WINDOWS7 系统中建立文件夹映射

    如何在WIN7中建立文件夹映射,还有以及MKLINK的具体使用方法: 步骤如下: 1.以映射d盘1文件夹为例: 2.按win+r,输入cmd,点击确定: 3.提示符后输入mklink /J " ...

  7. Eslint报错整理与解决方法

    1.‘Unexpected tab character’ 字面意思理解呢就是意想不到的制表符,当时出现的时候就是我习惯的使用Tab键去打空格,但是eslint默认不认可Tab,所以解决方法很简单: 在 ...

  8. Codeforces 1216F. Wi-Fi

    传送门 这个题一眼 $dp$ 就是设 $f[i][0/1]$ 表示我们只考虑前 $i$ 个位置,并且保证覆盖了前 $i$ 个位置,当前位置 选/不选 的最小代价 考虑转移,设题目给出的字符串为 $s$ ...

  9. Mac下的Web性能压力测试工具:ab(ApacheBench)

    Web开发,少不了的就是压力测试,它是评估一个产品是否合格上线的基本标准. ab是一种用于测试Apache超文本传输协议(HTTP)服务器的工具.apache自带ab工具,可以测试Apache.IIS ...

  10. 111、什么是stack (Swarm18)

    参考https://www.cnblogs.com/CloudMan6/p/8119150.html   什么是 stack ?    在将这个之前先回顾一下前面部署WordPress的过程:     ...