CF932F(李超线段树+dp)
此题又是新玩法, 李超线段树合并优化\(dp\)
一个显然的\(\Theta(n^2)dp\): \(dp[x]\)表示从x出发到叶子节点的最小代价
\(dp[x] = \min(dp[y] + a[x] * b[y]) ~~(y \in subtree(x))\)
如果我们将\(b[y]\)看成斜率, \(dp[y]\)看成纵截距, \(a[x]\)看成横坐标, 那么问题转为了在平面上有一些直线, 选出与直线\(x = a[x]\)相交的最靠下的点吗, 李超线段树板题, 但这道题出到了树上所以要用上线段树合并 因为有负数所以要整体右移一下, 相应的直线也需变换, 具体见代码
代码:
#pragma GCC optimize(3) #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define re register #define ll long long using namespace std; template <typename T> void read(T &x) { x = 0; bool f = 0; char c = getchar(); for (;!isdigit(c);c=getchar()) if (c=='-') f=1; for (;isdigit(c);c=getchar()) x=x*10+(c^48); if (f) x=-x; } template <typename T> void write(T x) { if (x < 0) putchar('-'), x = -x; if (x >= 10) write(x / 10); putchar('0' + x % 10); } const int N = 200500; const int Delta = 100005; const int Len = Delta << 1; int h[N], ne[N<<1], to[N<<1]; int T[N], tot, cnt; inline void add(int x, int y) { ne[++tot] = h[x], to[tot] = y, h[x] = tot; } int ls[N<<5], rs[N<<5], p[N<<5]; ll n, ans[N], a[N], b[N]; struct node { ll k, b; }line[N]; inline ll calc(int num, ll x) { return line[num].k * x + line[num].b; } void insert(int &x, int l, int r, int num) { if (!x) return x = ++cnt, p[x] = num, void(); int mid = (l + r) >> 1; if (calc(p[x], mid) > calc(num, mid)) swap(p[x], num); if (calc(p[x], l) <= calc(num, l) && calc(p[x], r) <= calc(num, r)) return; if (calc(p[x], l) > calc(num, l)) insert(ls[x], l, mid, num); else insert(rs[x], mid + 1, r, num); } const ll INF = 0x7fffffffffff; ll query(int now, int l, int r, ll x) { if (!now) return INF; int mid = (l + r) >> 1; return min(calc(p[now], x), x <= mid ? query(ls[now], l, mid, x) : query(rs[now], mid + 1, r, x)); } int merge(int x, int y, int l, int r) { if (!x || !y) return x | y; insert(x, l, r, p[y]); int mid = (l + r) >> 1; ls[x] = merge(ls[x], ls[y], l, mid); rs[x] = merge(rs[x], rs[y], mid + 1, r); return x; } void dfs(int x, int fa) { for (re int i = h[x], y; i; i = ne[i]) { if ((y = to[i]) == fa) continue; dfs(y, x); T[x] = merge(T[x], T[y], 1, Len); } ans[x] = query(T[x], 1, Len, a[x] + Delta); if (ans[x] == INF) ans[x] = 0; line[x] = (node){b[x], ans[x] - b[x] * Delta}; insert(T[x], 1, Len, x); } int main() { read(n); for (re int i = 1;i <= n; i++) read(a[i]); for (re int j = 1;j <= n; j++) read(b[j]); for (re int i = 1;i < n; i++) { int x, y; read(x), read(y); add(x, y), add(y, x); } dfs(1, 0); for (re int i = 1;i <= n; i++) write(ans[i]), putchar(' '); return 0; }
来源:https://www.cnblogs.com/Hs-black/p/12271622.html