您的位置:首页 > 其它

【NOI2014】购票

2016-06-21 18:55 281 查看
点分治套cdq分治维护斜率优化dp

#include<bits/stdc++.h>
#define rep(i,k,n) for(int i=k;i<=(n);i++)
#define rep2(i,k,n) for(int i=k;i>=(n);i--)
#define  inf 0x7f7f7f7f7f7f7f7full
using namespace std;
typedef long long ll;
const int N=200005;
struct E{
int to,next;ll w;
E(int to=0,int next=0,ll w=0):to(to),next(next),w(w){}
}edge
;
int head
,tot=0;
void add(int x,int y,ll w){
edge[++tot]=E(y,head[x],w);head[x]=tot;
}
int n,T,fa
,mx
,sz
,vis
,root,Sum,tt=0;
ll dis
,d
,p
,L
,q
;
void getdis(int x){
for(int i=head[x];i;i=edge[i].next){
int v=edge[i].to;ll w=edge[i].w;
dis[v]=dis[x]+w;
getdis(v);
}
}
void getroot(int x){
sz[x]=1;mx[x]=0;
for(int i=head[x];i;i=edge[i].next){
int v=edge[i].to;
if(!vis[v]){
getroot(v);
mx[x]=max(mx[x],sz[v]);
sz[x]+=sz[v];
}
}mx[x]=max(mx[x],Sum-sz[x]);
if(mx[x]<mx[root])root=x;
}
bool cmp(int a,int b){
return dis[a]-L[a]>dis[b]-L[b];
}
int stk
,top=0;
void dfs(int x){
stk[++top]=x;
for(int i=head[x];i;i=edge[i].next){
int v=edge[i].to;
if(!vis[v])dfs(v);
}
}
struct point{
ll x,y;point(ll x=0,ll y=0):x(x),y(y){}
}Q
;int tq=0;
ll operator*(point a,point b){
return a.x*b.y-a.y*b.x;
}
point operator-(point a,point b){
return point(a.x-b.x,a.y-b.y);
}
ll get_ans(int x,point y){
return y.y+(dis[x]-y.x)*p[x]+q[x];
}
double kk(point a){
return (double)a.y/a.x;
}
void solve_query(int x){
ll ans=inf;
int l=1,r=tq;
while(l+2<r){
int l1=l+(r-l)/3;
int l2=l1+(r-l1)/2;
ll ans1=get_ans(x,Q[l1]);
ll ans2=get_ans(x,Q[l2]);
if(ans1<ans2)r=l2;
else l=l1;
}
rep(i,l,r)ans=min(ans,get_ans(x,Q[i]));
d[x]=min(d[x],ans);
}
void solve(int rt){
root=0;getroot(rt);int x=root;vis[x]=1;
if(x!=rt){
Sum=sz[rt]-sz[x];
solve(rt);
top=0;dfs(x);
sort(stk+1,stk+top+1,cmp);
int now=fa[x],j=1;
tq=0;
Q[++tq]=point(dis[now],d[now]);
while(j<=top && dis[stk[j]]-dis[now]>L[stk[j]])j++;

rep(i,j,top){
while(now!=rt && dis[stk[i]]-dis[fa[now]]<=L[stk[i]]){
now=fa[now];
point P=point(dis[now],d[now]);
while(tq>1 && kk(Q[tq]-Q[tq-1])<kk(P-Q[tq]))tq--;
Q[++tq]=P;
}
solve_query(stk[i]);
}

}else{top=0;dfs(x);}
rep(i,1,top)
if(dis[stk[i]]-dis[x]<=L[stk[i]])
d[stk[i]]=min(d[stk[i]],get_ans(stk[i],point(dis[x],d[x])));
for(int i=head[x];i;i=edge[i].next){
int v=edge[i].to;
if(!vis[v]){Sum=sz[v];
solve(v);
}
}
}
int main(){
//  freopen("in.in","r",stdin);
//  freopen("out.out","w",stdout);
scanf("%d%d",&n,&T);int x,y,w;
memset(d,0x3f,sizeof(d));d[1]=0;
rep(i,2,n){
scanf("%d%lld%lld%lld%lld",&fa[i],&w,&p[i],&q[i],&L[i]);
add(fa[i],i,w);
}getdis(1);
mx[0]=0x7f7f7f7f,Sum=n,root=0;
solve(1);
rep(i,2,n)printf("%lld\n",d[i]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  树分治 dp cdq