#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;
}
bzoj 3672 [Noi2014]购票 (线段树+凸壳)
最新推荐文章于 2022-09-23 17:02:26 发布