记录编号 255236 评测结果 AAAAAAAAAA
题目名称 [NOI 2014]购票 最终得分 100
用户昵称 Gravatarthomount 是否通过 通过
代码语言 C++ 运行时间 5.999 s
提交时间 2016-04-27 10:22:22 内存使用 44.54 MiB
显示代码纯文本
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
long long read() {
	char ch = getchar();
	while (ch < '0' || ch > '9') ch = getchar();
	long long ans = 0;
	while (ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0', ch = getchar();
	return ans;
}
const int N = 200010;
const long long ml = 1ll << 60;
const double eps = 1e-6;
struct edge {
	int x, y, next;
	long long z;
	edge(int x = 0, int y = 0, long long z = 0, int next = -1): x(x), y(y), z(z), next(next) {}
} e[N];
int h[N], ett = 0;
inline void match(int x, int y, long long z) {e[ett] = edge(x, y, z, h[x]); h[x] = ett++;}
struct info {
	int x;
	long long y, z;
} op[N];
long long ans[N], dist[N];
int fa[N], dp[N], size[N], son[N], par[N], id[N], ttt = 0;
void dfs1(int x) {
	dp[x] = dp[fa[x]] + 1;
	size[x] = 1; son[x] = 0;
	int p = h[x];
	while (p != -1) {
		dist[e[p].y] = dist[x] + e[p].z;
		dfs1(e[p].y);
		size[x] += size[e[p].y];
		if (!son[x] || size[e[p].y] > size[son[x]]) son[x] = e[p].y;
		p = e[p].next;
	}
}
void dfs2(int x, int P) {
	par[x] = P;
	id[x] = ++ttt;
	if (son[x]) dfs2(son[x], P);
	int p = h[x];
	while (p != -1) {
		if (e[p].y != son[x]) dfs2(e[p].y, e[p].y);
		p = e[p].next;
	}
}
struct point {
	long long x, y;
	point(long long x = 0, long long y = 0): x(x), y(y) {}
} p[N];
inline point operator - (point a, point b) {return point(a.x-b.x, a.y-b.y);}
inline int operator * (point a, point b) {return (((double)a.x*b.y - (double)a.y*b.x) > -eps) ? 1: -1;}
inline bool operator < (point a, point b) {return (a.x == b.x)? (a.y < b.y): (a.x < b.x);}
inline bool cmp(int x, int y) {return p[x] < p[y];}
struct node {
	int l, r, st, en;
	node * ls, * rs;
	node(int l = 0, int r = 0): l(l), r(r), st(0), en(0), ls(0), rs(0) {}
} d[N*2];
typedef node * link;
int ptt = 0;
link head;
link build(int l, int r) {
	d[++ptt] = node(l, r);
	link p = &d[ptt];
	if (l < r) {
		int mid = (l + r) >> 1;
		p->ls = build(l, mid);
		p->rs = build(mid+1, r);
	}
	return p;
}
int q[N*20], temp[N], top = 0;
void cal(link P) {
	int n = 0;
	for (int i = P->l; i <= P->r; i++) temp[++n] = i;
	sort(temp+1, temp+n+1, cmp);
	int up = top+1;
	for (int i = 1; i <= n; i++) {
		while (top > up && (p[temp[i]] - p[q[top]]) * (p[q[top]] - p[q[top-1]]) >= 0) top--;
		q[++top] = temp[i];
	}
	P->st = up, P->en = top;
}

long long get(int l, int r, long long k) {
	if (l == r) return p[q[r]].y - p[q[r]].x * k;	//区间为1的特判
	point temp = point(1, k);
	if ((p[q[r]] - p[q[r-1]]) * temp >= 0) return p[q[r]].y - p[q[r]].x * k;
	if (temp * (p[q[l+1]] - p[q[l]]) >= 0) return p[q[l]].y - p[q[l]].x * k;	//边界特判
	l++, r--;
	while (l < r) {
		int mid = (l + r) >> 1;
		int k1 = temp * (p[q[mid+1]] - p[q[mid]]), k2 = (p[q[mid]] - p[q[mid-1]]) * temp;
		if (k1 >= 0 && k2 >= 0) {l = r = mid; break;}
		if (k1 < 0) l = mid+1; else r = mid-1;
	}
	return p[q[l]].y - p[q[l]].x * k;
}
long long check(link p, int l, int r, long long k) {
	if (l > r) return ml;
	if (l <= p->l && p->r <= r) {
		if (!p->st) cal(p);
		return get(p->st, p->en, k);
	}
	int mid = (p->l + p->r) >> 1;
	long long ans = ml;
	if (l <= mid) ans = min(ans, check(p->ls, l, r, k));
	if (mid < r) ans = min(ans, check(p->rs, l, r, k));
	return ans;
}
int find(int l, int r, long long k) {
	if (k < p[l].x) return l;
	if (k > p[r].x) return r+1;
	while (l < r) {
		int mid = (l + r) >> 1;
		if (k <= p[mid].x) r = mid; else l = mid+1;
	}
	return l;
}
long long update(int x) {
	int y = fa[x], fy = par[y];
	long long ans = ml;
	while (y && dist[x] - dist[y] <= op[x].z) {
		int st;		//本段起点
		if (dist[x] - dist[fy] <= op[x].z) st = id[fy];	else st = find(id[fy], id[y], dist[x] - op[x].z);
		ans = min(ans, check(head, st, id[y], op[x].x));
		y = fa[fy]; fy = par[y];
	}
	return ans + dist[x] * op[x].x + op[x].y;
}

int main() {
	freopen("ticket.in", "r", stdin);
	freopen("ticket.out", "w", stdout);
	int n = read(), T = read();
	memset(h, -1, sizeof(h));
	for (int i = 2; i <= n; i++) {
		int fx = read();
		long long sx = read();
		match(fx, i, sx);
		fa[i] = fx;
		op[i].x = read(), op[i].y = read(), op[i].z = read();
	}
	dist[1] = 0; dp[0] = 0;
	dfs1(1);	// son size dist dp
	dfs2(1, 1);	// par id 
	
	head = build(1, n);
	ans[1] = 0; p[1] = point(0, 0);
	for (int i = 2; i <= n; i++) {
		printf("%lld\n", ans[i] = update(i));
		p[id[i]] = point(dist[i], ans[i]);
	}
	return 0;
}