小清新数据结构优化 dp。
思路
考虑基本的 dp 式。
\[\begin{aligned} f_{x}&=w_{x}+\max_{i 是 x 的祖先}v_{x}\times (dep_{x}-dep_{i})+f_i\\ &=w_{x}+v_{x}\times dep_{x}+\max_{i 是 x 的祖先}-dep_{i}\times v_{x}+f_i \end{aligned}\]发现 \(-dep_{i}\times v_{x}+f_i\) 是一次函数形式。
可以用李超树优化。
由于李超树是严格 \(O(\log n)\),所以肯定支持撤回。
我们只需要遍历一遍即可。
时间复杂度 \(O(n\log n)\)。
Code
/*
! 如果没有天赋,那就一直重复
! Created: 2024/06/17 07:47:35
*/
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define fro(i, x, y) for (int i = (x); i <= (y); i++)
#define pre(i, x, y) for (int i = (x); i >= (y); i--)
const int N = 1e5 + 10;
const int I = 1e9;
int n, ct, tp, tt, rt;
int w[N], v[N], f[N], dep[N], head[N];
int t[N << 5];
int ls[N << 5];
int rs[N << 5];
int*s1[N << 5];
int s2[N << 5];
struct edge {
int to, nxt, val;
} e[N << 1];
struct line {
int k, b;
inline int get(int x) { return k * x + b; }
} d[N];
inline void add(int x, int y, int z) {
e[++ct] = {y, head[x], z}, head[x] = ct;
e[++ct] = {x, head[y], z}, head[y] = ct;
}
inline void bak(int t) {
while (tp > t) *s1[tp] = s2[tp], tp--;
}
inline void evl(int&x, int y) {
++tp, s1[tp] = &x, s2[tp] = x, x = y;
}
inline void upd(int&p, int l, int r, int x) {
if (!p) p = ++tt;
if (!t[p]) return evl(t[p], x);
if (l == r) return d[t[p]].get(l) > d[x].get(l) ? evl(t[p], x) : void();
int mid = (l + r) >> 1, cur = t[p];
if (d[t[p]].get(mid) > d[x].get(mid)) evl(t[p], x), x = cur;
if (d[t[p]].get(l) > d[x].get(l)) upd(ls[p], l, mid, x);
if (d[t[p]].get(r) > d[x].get(r)) upd(rs[p], mid + 1, r, x);
}
inline int ask(int p, int l, int r, int x) {
if (!p || !t[p]) return 1e18;
int mid = (l + r) >> 1, num = d[t[p]].get(x);
if (mid >= x) num = min(num, ask(ls[p], l, mid, x));
if (mid < x) num = min(num, ask(rs[p], mid + 1, r, x));
return num;
}
inline void dfs(int now, int fa) {
if (now != 1) {
f[now] = w[now] + v[now] * dep[now] + min(0ll, ask(rt, 0, I, v[now]));
d[now] = {-dep[now], f[now]};
upd(rt, 0, I, now);
}
int tim = tp;
for (int i = head[now]; i; i = e[i].nxt) {
if (e[i].to == fa) continue;
dep[e[i].to] = dep[now] + e[i].val;
dfs(e[i].to, now);
bak(tim);
}
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
fro(i, 1, n - 1) {
int a, b, c;
cin >> a >> b >> c;
add(a, b, c);
}
fro(i, 2, n) cin >> w[i] >> v[i];
dfs(1, 0);
fro(i, 2, n) cout << f[i] << " ";
return 0;
}
标签:P10602,Harbingers,int,题解,get,mid,tp,dep,now
From: https://www.cnblogs.com/JiaY19/p/18252250