bzoj 3672 [Noi2014]購票 (線段樹+凸殼)
阿新 • • 發佈:2019-02-06
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <bitset> #include <vector> using namespace std; #define N 200020 #define M 400020 #define mod 1000000007 #define inf 0x3f3f3f3f #define LL long long #define ls (i << 1) #define rs (ls | 1) #define md (ll + rr >> 1) #define lson ll, md, ls #define rson md + 1, rr, rs int n, t; int fst[N], nxt[M], vv[M], e; LL cost[M]; int p[N], fa[N]; LL s[N], q[N], l[N]; int dep[N], tp[N]; int stk[N], top; LL dis[N]; LL dp[N]; void init() { memset(fst, -1, sizeof fst); e = 0; } void add(int u, int v, LL c) { cost[e] = c, vv[e] = v, nxt[e] = fst[u], fst[u] = e++; } int calc(LL d, LL x) { if(d == 0) return 1; int l = 0, r = top - 1; while(l < r) { int mid = (l + r) / 2; if(d - dis[stk[mid]] <= x) r = mid; else l = mid + 1; } return stk[l]; } void dfs1(int u, int d) { tp[u] = calc(dis[u], l[u]); stk[top++] = u; dep[u] = d; for(int i = fst[u]; ~i; i = nxt[i]) { int v = vv[i]; dis[v] = dis[u] + cost[i]; dfs1(v, d + 1); } top--; } struct node { LL x, y; node() {} node(LL x, LL y):x(x), y(y) {} }pool[N * 20]; int pool_sz; node* creat(int len) { node *ret = pool + pool_sz; pool_sz += len; return ret; } struct change { int pos; node a; int len; int i; change() {} change(int pos, node a, int len, int i): pos(pos), a(a), len(len), i(i) {} }cc[N * 20]; int cc_cnt; struct ch { node *p; int len; void insert(node v, int x) { if(len == 0 || len == 1) { cc[cc_cnt++] = change(len, p[len], len, x); p[len++] = v; return; } int l = 0, r = len - 1; while(l < r) { int mid = (l + r) / 2; node a = p[mid + 1]; node b = p[mid]; if(1.0 * (v.y - a.y) / (v.x - a.x) < 1.0 * (a.y - b.y) / (a.x - b.x)) r = mid; else l = mid + 1; } cc[cc_cnt++] = change(l + 1, p[l + 1], len, x); p[l + 1] = v; len = l + 2; } LL query(int k) { int l = 0, r = len - 1; while(l < r) { int mid = (l + r) / 2; node a = p[mid + 1], b = p[mid]; if(1.0 * (a.y - b.y) / (a.x - b.x) >= k) r = mid; else l = mid + 1; } return p[l].y - k * p[l].x; } void rollback(change &x) { len = x.len; p[x.pos] = x.a; } }ss[N << 2]; void build(int ll, int rr, int i) { ss[i].p = creat(rr - ll + 1); ss[i].len = 0; if(ll == rr) return; build(lson); build(rson); } void update(int x, node v, int ll, int rr, int i) { ss[i].insert(v, i); if(ll == rr) { return; } if(x <= md) update(x, v, lson); else update(x, v, rson); } LL query(int l, int r, int v, int ll, int rr, int i) { if(ll == l && rr == r) { return ss[i].query(v); } if(r <= md) return query(l, r, v, lson); if(l > md) return query(l, r, v, rson); return min(query(l, md, v, lson), query(md + 1, r, v, rson)); } void dfs2(int u) { if(u == 1) dp[u] = 0; else { dp[u] = query(dep[tp[u]], dep[u] - 1, p[u], 0, n, 1); dp[u] += dis[u] * p[u] + q[u]; } int tmp = cc_cnt; update(dep[u], node(dis[u], dp[u]), 0, n, 1); for(int i = fst[u]; ~i; i = nxt[i]) { int v = vv[i]; dfs2(v); } while(cc_cnt != tmp) { --cc_cnt; ss[cc[cc_cnt].i].rollback(cc[cc_cnt]); } } int main() { scanf("%d%d", &n, &t); init(); for(int i = 2; i <= n; ++i) { scanf("%d%lld%d%lld%lld", &fa[i], &s[i], &p[i], &q[i], &l[i]); add(fa[i], i, s[i]); } dfs1(1, 0); build(0, n, 1); dfs2(1); for(int i = 2; i <= n; ++i) printf("%lld\n", dp[i]); return 0; }