题面
题解
设表示从开始旅行的最大有趣度,从上面的简化题意中可知,该值只与相邻两处景点有关,于是有:
设为从1到的路径长度,把化成,可以得出
观察一下发现,每个点可以看作一条直线,然后查询所有直线在处的最大值。
这个问题非常熟悉,可以用李超树解决。怎么把所有儿子的李超树的信息合并起来呢?也非常熟悉,用线段树合并即可。
(为了写这篇题解,我还专门水写了两者的博客😥)
由于每个儿子的直线数加起来不超过n,线段树合并总复杂度不超过,由于李超树插入的是直线,每次复杂度
总复杂度
代码
这绝对是这题最短的代码之一(80行)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<vector>
#define ll long long
#define MAXN 1000005
#define INF 0x7f7f7f7f
#define R 2000000000ll
using namespace std;
inline ll read(){
ll x=0;bool f=1;char s=getchar();
while((s<'0'||s>'9')&&s>0){if(s=='-')f^=1;s=getchar();}
while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+s-'0',s=getchar();
return f?x:-x;
}
int n,IN,root[MAXN];
ll a[MAXN],b[MAXN],d[MAXN],ans[MAXN];
struct itn{
int v;ll w;
itn(){}
itn(int V,ll W){v=V,w=W;}
};
vector<itn>G[MAXN];
struct lcs{ //动态开点李超树
int ls,rs;ll k,b;lcs(){}
lcs(ll K,ll B){ls=rs=0,k=K,b=B;}
}t[MAXN<<4];
inline void add(int x,ll l,ll r,ll k,ll b){
if(x==0)return;
ll tk=t[x].k,tb=t[x].b,mid=(l+r)>>1;
if(l*k+b>=l*tk+tb&&r*k+b>=r*tk+tb){t[x].k=k,t[x].b=b;return;}
else if(l*k+b<l*tk+tb&&r*k+b<r*tk+tb)return;
else{
if(!t[x].ls)t[x].ls=++IN,t[IN]=lcs(tk,tb);
else add(t[x].ls,l,mid,tk,tb);
if(!t[x].rs)t[x].rs=++IN,t[IN]=lcs(tk,tb);
else add(t[x].rs,mid+1,r,tk,tb);
t[x].k=k,t[x].b=b;
}
}
inline int mergg(int x,int y,ll l,ll r){
if(!x||!y)return x|y;
ll mid=(l+r)>>1;
t[x].ls=mergg(t[x].ls,t[y].ls,l,mid),t[y].ls=0;
t[x].rs=mergg(t[x].rs,t[y].rs,mid+1,r),t[y].rs=0;
add(x,l,r,t[y].k,t[y].b);
return x;
}
inline ll sch(int x,ll l,ll r,ll g){
if(x==0)return -INF;
ll mid=(l+r)>>1,res=g*t[x].k+t[x].b;
if(g<=mid)res=max(res,sch(t[x].ls,l,mid,g));
else res=max(res,sch(t[x].rs,mid+1,r,g));
return res;
}
inline void dfs(int x,int fa,ll dx){
d[x]=dx,root[x]=++IN,t[IN]=lcs(0,-INF);
for(int i=0;i<G[x].size();i++)
if(G[x][i].v!=fa){
int v=G[x][i].v;ll w=G[x][i].w;
dfs(v,x,dx+w),root[x]=mergg(root[x],root[v],0,R);
}
ans[x]=max(0ll,sch(root[x],0,R,a[x]+d[x]));
add(root[x],0,R,b[x],ans[x]-b[x]*d[x]);
}
int main()
{
n=read();
for(int i=1;i<=n;i++)a[i]=read(),b[i]=read();
for(int i=1;i<n;i++){
int u=read(),v=read();ll w=read();
G[u].push_back(itn(v,w)),G[v].push_back(itn(u,w));
}
dfs(1,0,0);
for(int i=1;i<=n;i++)printf("%lld\n",ans[i]);
return 0;
}