记录编号 260611 评测结果 AAAAAAAAAA
题目名称 [NOI 2014]购票 最终得分 100
用户昵称 GravatarTenderRun 是否通过 通过
代码语言 C++ 运行时间 7.199 s
提交时间 2016-05-14 09:25:49 内存使用 25.49 MiB
显示代码纯文本
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
using namespace std;
const long long INF=(long long)1e18;
const int maxn=200010;
int cnt,fir[maxn],to[maxn],nxt[maxn],son[maxn],sz[maxn],fa[maxn],n,t;
long long val[maxn],P[maxn],Q[maxn],S[maxn],F[maxn],L[maxn];
void addedge(int a,int b,long long c){
	nxt[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;val[cnt]=c;
}

void DFS(int x){
	sz[x]=1;
	for(int i=fir[x];i;i=nxt[i])
		if(to[i]!=fa[x]){
			fa[to[i]]=x;
			S[to[i]]=S[x]+val[i];
			DFS(to[i]);
			sz[x]+=sz[to[i]];
			if(sz[son[x]]<sz[to[i]])
				son[x]=to[i];
		}
}

int top[maxn],ID[maxn],RID[maxn],tot;
void DFS(int x,int tp){
	ID[x]=++tot;RID[tot]=x;top[x]=tp;
	if(son[x])DFS(son[x],tp);
	for(int i=fir[x];i;i=nxt[i])
		if(to[i]!=fa[x]&&to[i]!=son[x])
			DFS(to[i],to[i]);
}

struct Slope{
	vector<int>id;
	void Insert(int x){
		int p=id.size()-1;
		id.push_back(x);
		while(true){
			if(p<=0)break;
			if(1.0*(F[id[p]]-F[id[p-1]])/(S[id[p]]-S[id[p-1]])<1.0*(F[id[p+1]]-F[id[p]])/(S[id[p+1]]-S[id[p]]))break;
			id.pop_back();id.pop_back();id.push_back(x);p--;
		}
		return; 
	}
	
	long long Query(int p){
		int p1=-1,p2;
		for(int i=20;i>=0;i--){
			p2=p1+(1<<i);
			if(p2>=id.size()-1)continue;
			if(1.0*(F[id[p2+1]]-F[id[p2]])/P[p]<=1.0*(S[id[p2+1]]-S[id[p2]]))
				p1+=1<<i;
		}
		p1+=1;
		return F[id[p1]]+(S[p]-S[id[p1]])*P[p]+Q[p];
	}
}slope[maxn<<2];

long long Query(int x,int l,int r,int a,int b,int p){
	if(l>=a&&r<=b)
		return slope[x].Query(p);
		
	int mid=(l+r)>>1;
	long long ret=INF;
	if(a<=mid)
		ret=Query(x<<1,l,mid,a,b,p);
	if(mid<b)
		ret=min(ret,Query(x<<1|1,mid+1,r,a,b,p));
	return ret;		
}

void Insert(int x,int l,int r,int p){
	slope[x].Insert(p);
	if(l==r)return;
	int mid=(l+r)>>1;
	if(mid>=ID[p])
		Insert(x<<1,l,mid,p);
	else
		Insert(x<<1|1,mid+1,r,p);	
}

long long Get_ans(int p){ 
	int pos=fa[p];
	long long ret=INF;
	while(pos){
		if(S[p]-L[p]>S[pos])break;
		int p1=ID[top[pos]]-1;
		for(int i=20;i>=0;i--)
			if(p1+(1<<i)<ID[pos]&&S[RID[p1+(1<<i)]]<S[p]-L[p])
				p1+=1<<i;		
		ret=min(ret,Query(1,1,n,p1+1,ID[pos],p));
		pos=fa[top[pos]];
	}
	return ret;
}

void Solve(int x){
	F[x]=x==1?0:Get_ans(x);
	Insert(1,1,n,x);
	for(int i=fir[x];i;i=nxt[i])
		if(to[i]!=son[x])
			Solve(to[i]);
	if(son[x])
		Solve(son[x]);		
	return;
}

int main(){
#ifndef ONLINE_JUDGE 
	freopen("ticket.in","r",stdin);
	freopen("ticket.out","w",stdout);
#endif 
	scanf("%d%d",&n,&t);
	for(int i=2,a,b;i<=n;i++){
		scanf("%d%d%lld%lld%lld",&a,&b,&P[i],&Q[i],&L[i]);
		addedge(a,i,b*1ll);
	}
	
	DFS(1);
	DFS(1,1);
	
	Solve(1);
	for(int i=2;i<=n;i++)
		printf("%lld\n",F[i]);
	return 0;
}