[Bzoj1767][Ceoi2009]harbingers (树上斜率优化)
Posted zcr-blog
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Bzoj1767][Ceoi2009]harbingers (树上斜率优化)相关的知识,希望对你有一定的参考价值。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 100005;
struct node{
int pre, to, val;
}edge[MAXN << 1];
int n, head[MAXN], tot, fa[MAXN], stk[MAXN], top, pos[MAXN];
ll W[MAXN], V[MAXN], dp[MAXN], dis[MAXN];
void add_edge(int u, int v, int l) {
edge[++tot] = node{head[u], v, l};
head[u] = tot;
}
double slope(int i, int j) {
if (dis[i] == dis[j]) return 1e18;
return 1.0 * (dp[i] - dp[j]) / (dis[i] - dis[j]);
}
void dfs(int x) {
if (x != 1) {
//二分统计答案
int l = 1, r = top - 1, now = top;
while (l <= r) {
int mid = (l + r) >> 1;
if (slope(stk[mid], stk[mid + 1]) > V[x]) now = mid, r = mid - 1;
else l = mid + 1;
}
dp[x] = dp[stk[now]] - V[x] * dis[stk[now]] + W[x] + dis[x] * V[x];
}
bool flag = true;
int tmp, temp;
pos[x] = top;//pos记录每个点加进去之前的栈到哪个位置
if (top == 0) {//如果当前栈里没有点
stk[++top] = x;
} else {
int l = 2, r = top, now = 1;
while (l <= r) {
int mid = (l + r) >> 1;
if (slope(stk[mid - 1], stk[mid]) < slope(stk[mid - 1], x)) now = mid, l = mid + 1;
else r = mid - 1;
}
flag = false;
tmp = stk[now + 1];
stk[now + 1] = x;
top = now + 1;
temp = now;
}
for (int i = head[x]; i; i = edge[i].pre) {
int y = edge[i].to;
if (y == fa[x]) continue;
fa[y] = x;
dis[y] = dis[x] + edge[i].val;
dfs(y);
}
top = pos[x];
if (!flag) stk[temp + 1] = tmp;
}
int main() {
memset(dp, 0x3f, sizeof(dp));
scanf("%d", &n);
for (int i = 1; i < n; i++) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add_edge(a, b, c);
add_edge(b, a, c);
}
for (int i = 2; i <= n; i++) scanf("%lld%lld", &W[i], &V[i]);
dp[1] = 0;
dfs(1);
for (int i = 2; i <= n; i++) printf("%lld ", dp[i]);
return 0;
}
以上是关于[Bzoj1767][Ceoi2009]harbingers (树上斜率优化)的主要内容,如果未能解决你的问题,请参考以下文章
[Bzoj1767][Ceoi2009]harbingers (树上斜率优化)
bzoj 1767: [Ceoi2009]harbingers
BZOJ——T 1800: [Ahoi2009]fly 飞行棋