bzoj 3672 [Noi2014]购票 (线段树+凸壳)

时间:2023-02-10 17:14:07
#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;
}