题意:给定树,有点权。求一条路径使得最小点权 * 总点数最大。只需输出这个最大值。5w。

解:树上路径问题,点分治。

考虑合并两个子树的时候,答案的形式是val1 * (d1 + d2),当1是新插入的节点的时候,只需在val比它大的点中选出一个最大的d2,这树状数组就可以做到。

当2是新插入的节点时候,好像需要凸包了?但是我们完全不虚啊,因为我们倒序枚举子树就能让2在1之前插入。

于是正反枚举两次子树,拿树状数组维护一下后缀最大值就行了。

复杂度O(nlog2n)

 /**
* There is no end though there is a start in space. ---Infinity.
* It has own power, it ruins, and it goes though there is a start also in the star. ---Finite.
* Only the person who was wisdom can read the most foolish one from the history.
* The fish that lives in the sea doesn't know the world in the land.
* It also ruins and goes if they have wisdom.
* It is funnier that man exceeds the speed of light than fish start living in the land.
* It can be said that this is an final ultimatum from the god to the people who can fight.
*
* Steins;Gate
*/ #include <bits/stdc++.h> #define forson(x, i) for(int i = e[x]; i; i = edge[i].nex) typedef long long LL;
const int N = , INF = 0x3f3f3f3f; struct Edge {
int nex, v;
}edge[N << ], edge2[N << ]; int tp, tp2; int e[N], n, siz[N], _n, root, small, e2[N], xx, d[N], Val[N];
LL val[N], X[N], ans;
bool del[N]; inline void add(int x, int y) {
tp++;
edge[tp].v = y;
edge[tp].nex = e[x];
e[x] = tp;
return;
} inline void add2(int x, int y) {
tp2++;
edge2[tp2].v = y;
edge2[tp2].nex = e2[x];
e2[x] = tp2;
return;
} namespace ta {
int ta[N];
inline void add(int x, int v) {
x = xx + - x;
for(int i = x; i <= xx; i += i & (-i)) {
ta[i] = std::max(ta[i], v);
}
return;
}
inline void del(int x) {
x = xx + - x;
for(int i = x; i <= xx; i += i & (-i)) {
ta[i] = -INF;
}
return;
}
inline int getMax(int x) {
x = xx + - x;
int ans = -INF;
for(int i = x; i; i -= i & (-i)) {
ans = std::max(ans, ta[i]);
}
return ans;
}
} void getroot(int x, int f) {
siz[x] = ;
int large = ;
forson(x, i) {
int y = edge[i].v;
if(y == f || del[y]) continue;
getroot(y, x);
siz[x] += siz[y];
if(siz[y] > large) {
large = siz[y];
}
}
if(_n - siz[x] > large) {
large = _n - siz[x];
}
if(small > large) {
small = large;
root = x;
}
return;
} void DFS_1(int x, int f) {
siz[x] = ;
d[x] = d[f] + ;
Val[x] = std::min(Val[f], (int)val[x]);
ans = std::max(ans, X[Val[x]] * (d[x] + ta::getMax(Val[x])));
forson(x, i) {
int y = edge[i].v;
if(del[y] || y == f) continue;
DFS_1(y, x);
siz[x] += siz[y];
}
return;
} void DFS_2(int x, int f) {
ta::add(Val[x], d[x] + );
forson(x, i) {
int y = edge[i].v;
if(y == f || del[y]) continue;
DFS_2(y, x);
}
return;
} void DFS_3(int x, int f) {
ta::del(Val[x]);
forson(x, i) {
int y = edge[i].v;
if(del[y] || y == f) {
continue;
}
DFS_3(y, x);
}
return;
} void poi_div(int x) {
small = INF;
getroot(x, );
x = root; d[x] = ;
Val[x] = val[x];
ta::add(Val[x], );
forson(x, i) {
int y = edge[i].v;
if(del[y]) continue;
DFS_1(y, x);
DFS_2(y, x);
}
DFS_3(x, );
// ---------
for(int i = e2[x]; i; i = edge2[i].nex) {
int y = edge2[i].v;
if(del[y]) continue;
DFS_1(y, x);
DFS_2(y, x);
}
ans = std::max(ans, X[val[x]] * ta::getMax(val[x]));
DFS_3(x, ); del[x] = ;
forson(x, i) {
int y = edge[i].v;
if(del[y]) continue;
_n = siz[y];
poi_div(y);
}
return;
} int main() { scanf("%d", &n);
for(int i = ; i <= n; i++) {
scanf("%lld", &val[i]);
X[i] = val[i];
}
std::sort(X + , X + n + );
xx = std::unique(X + , X + n + ) - X - ;
for(int i = ; i <= n; i++) {
val[i] = std::lower_bound(X + , X + xx + , val[i]) - X;
}
ans = X[xx];
for(int i = , x, y; i < n; i++) {
scanf("%d%d", &x, &y);
add(x, y); add(y, x);
}
for(int x = ; x <= n; x++) {
forson(x, i) {
add2(x, edge[i].v);
}
} poi_div(); printf("%lld\n", ans);
return ;
}

AC代码

题外话:感觉能树形DP,但是要线段树合并 + 凸包合并,虚的一批...

还发现了一个O(nlogn)的做法,只需多叉转二叉然后O(n) - O(1)lca即可实现,瓶颈在于排序...

然而这题是边分治模板题...

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

  1. BZOJ2870—最长道路tree

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

  2. BZOJ2870: 最长道路tree

    题解: 子树分治的做法可以戳这里:http://blog.csdn.net/iamzky/article/details/41120733 可是码量... 这里介绍另一种好写又快的方法. 我们还是一颗 ...

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

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

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

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

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

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

  6. 【BZOJ2870】最长道路(边分治)

    [BZOJ2870]最长道路(边分治) 题面 BZOJ权限题 Description H城很大,有N个路口(从1到N编号),路口之间有N-1边,使得任意两个路口都能互相到达,这些道路的长度我们视作一样 ...

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

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

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

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

  9. 【BZOJ2870】最长道路

    权限题 题意 给出一棵树,点有点权,找到树上的一条路径使得路径上点的个数和其中点权最小的点的点权之积最大,输出最大值. Sol 边分治板子题啦. 边分治后对于分出来的两棵子树 , 按到左右根的最小点权 ...

随机推荐

  1. ButterKnife注解式绑定控件

    Butter Knife Android为控件设计的注解绑定库. github地址:https://github.com/JakeWharton/butterknife 添加依赖:(具体看github ...

  2. gitbook 入门教程之常用命令详解

    不论是 gitbook-cli 命令行还是 gitbook editor 编辑器都离不开 gitbook 命令的操作使用,所以再次了解下常用命令. 注意 gitbook-cli 是 gitbook 的 ...

  3. 如何解决夜神模拟器连不上adb的问题

    要搞一个安卓的项目.由于电脑系统是年前刚刚重装的,系统里啥都没有,于是临时安装了一下android studio 2.2,然后又装了一个夜神模拟器.工程打开后,编译通过了,于是打开夜神模拟器,想要通过 ...

  4. VSCode的Python扩展下程序运行的几种方式与环境变量管理

    在VSCode中编写Python程序时,由于有些地方要使用环境变量,但是发现设置的环境变量有时不起作用,花了点时间研究了一下,过程不表,直接说结论. 首先,环境变量的设置,Python扩展中有三种方式 ...

  5. Linux内存描述之高端内存--Linux内存管理(五)

    1. 内核空间和用户空间 过去,CPU的地址总线只有32位, 32的地址总线无论是从逻辑上还是从物理上都只能描述4G的地址空间(232=4Gbit),在物理上理论上最多拥有4G内存(除了IO地址空间, ...

  6. LeetCode算法题-Can Place Flowers(Java实现)

    这是悦乐书的第272次更新,第287篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第140题(顺位题号是605).假设你有一个花坛,其中一些地块是种植的,有些则不是. 然 ...

  7. JDBC获得连接时报connection refused

    1,检查数据库服务器的IP是否正确. 2,检查用户名密码是否正确. 3,检查SID,获selecte instance_name from v$instance;

  8. kernel笔记——内核同步与锁

    内核同步 内核同步解决并发带来的问题,多个线程对同一数据进行修改,数据会出现不一致的情况,同步用于保护共享数据等资源. 有两种形式的并发: 同时进行式并发,在不同cpu上执行的进程同时访问共享数据 二 ...

  9. 转://诊断 Grid Infrastructure 启动问题 (文档 ID 1623340.1) .

    文档内容   用途   适用范围   详细信息   启动顺序:   集群状态   问题 1: OHASD 无法启动   问题 2: OHASD Agents  未启动   问题 3: OCSSD.BI ...

  10. 【vue】项目目录结构及使用多的知识点

    项目目录: Node_modules/npm安装的该项目的依赖库 vuex/文件夹存放的是和 Vuex store 相关的东西(state对象,actions,mutations) router/文件 ...