链接
http://acm.hdu.edu.cn/showproblem.php?pid=6201
题解
枚举在哪个点买,设它是
v
v
v,那么这个点上的最大收益=
a
v
+
m
a
x
(
−
d
i
s
t
(
u
,
v
)
−
a
u
)
a_v+max(-dist(u,v)-a_u)
av+max(−dist(u,v)−au)
从一个点走向一个儿子结点,子树中点的
−
d
i
s
t
(
u
,
v
)
−
a
u
-dist(u,v)-a_u
−dist(u,v)−au会发生变化,而子树在
d
f
s
dfs
dfs序中是连续的一段
线段树维护一下就好了
代码
#include <bits/stdc++.h>
#define maxn 100010
#define maxe 200010
#define iinf 0x3f3f3f3f
using namespace std;
struct Graph
{
int etot, head[maxn], to[maxe], next[maxe], w[maxe];
void clear(int N)
{
int i;
for(i=1;i<=N;i++)head[i]=0;
for(i=1;i<=etot;i++)to[i]=next[i]=w[i]=0;
N=etot=0;
}
void adde(int a, int b, int c){to[++etot]=b;w[etot]=c;next[etot]=head[a];head[a]=etot;}
}G;
struct SegmentTree
{
#define inf 0x3f3f3f3f
int mn[maxn<<2], mx[maxn<<2], sum[maxn<<2], add[maxn<<2], set[maxn<<2], L[maxn<<2], R[maxn<<2];
void maketag_set(int o, int v)
{
add[o]=0;
set[o]=v;
mx[o]=mn[o]=v;
sum[o]=(R[o]-L[o]+1)*v;
}
void maketag_add(int o, int v)
{
add[o]+=v;
mx[o]+=v, mn[o]+=v;
sum[o]+=(R[o]-L[o]+1)*v;
}
void pushdown(int o)
{
if(L[o]==R[o])return;
if(~set[o])
{
maketag_set(o<<1,set[o]);
maketag_set(o<<1|1,set[o]);
set[o]=-1;
}
if(add[o])
{
maketag_add(o<<1,add[o]);
maketag_add(o<<1|1,add[o]);
add[o]=0;
}
}
void pushup(int o)
{
mx[o]=max(mx[o<<1],mx[o<<1|1]);
mn[o]=max(mn[o<<1],mn[o<<1|1]);
sum[o]=sum[o<<1]+sum[o<<1|1];
}
void build(int o, int l, int r, int* array)
{
int mid(l+r>>1);
L[o]=l, R[o]=r;
add[o]=0;
set[o]=-1;
if(l==r)
{
mn[o]=mx[o]=sum[o]=array[l];
return;
}
build(o<<1,l,mid,array);
build(o<<1|1,mid+1,r,array);
pushup(o);
}
void segset(int o, int l, int r, int v)
{
int mid(L[o]+R[o]>>1);
if(l<=L[o] and r>=R[o]){maketag_set(o,v);return;}
pushdown(o);
if(l<=mid)segset(o<<1,l,r,v);
if(r>mid)segset(o<<1|1,l,r,v);
pushup(o);
}
void segadd(int o, int l, int r, int v)
{
int mid(L[o]+R[o]>>1);
if(l<=L[o] and r>=R[o]){maketag_add(o,v);return;}
pushdown(o);
if(l<=mid)segadd(o<<1,l,r,v);
if(r>mid)segadd(o<<1|1,l,r,v);
pushup(o);
}
int segsum(int o, int l, int r)
{
pushdown(o);
int mid(L[o]+R[o]>>1), ans(0);
if(l<=L[o] and r>=R[o])return sum[o];
if(l<=mid)ans+=segsum(o<<1,l,r);
if(r>mid)ans+=segsum(o<<1|1,l,r);
return ans;
}
int segmin(int o, int l, int r)
{
int mid(L[o]+R[o]>>1), ans(inf);
if(l<=L[o] and r>=R[o])return mn[o];
pushdown(o);
if(l<=mid)ans=min(ans,segmin(o<<1,l,r));
if(r>mid)ans=min(ans,segmin(o<<1|1,l,r));
return ans;
}
int segmax(int o, int l, int r)
{
int mid(L[o]+R[o]>>1), ans(-inf);
if(l<=L[o] and r>=R[o])return mx[o];
pushdown(o);
if(l<=mid)ans=max(ans,segmax(o<<1,l,r));
if(r>mid)ans=max(ans,segmax(o<<1|1,l,r));
return ans;
}
#undef inf
}segtree;
int tim, ltid[maxn], rtid[maxn], n, a[maxn], v[maxn], ans, N;
void dfs0(int pos, int pre)
{
ltid[pos]=++tim;
for(auto p=G.head[pos];p;p=G.next[p])
if(G.to[p]!=pre)
dfs0(G.to[p],pos);
rtid[pos]=tim;
}
void dfs1(int pos, int pre, int dist)
{
v[ltid[pos]]=-dist+a[pos];
for(auto p=G.head[pos];p;p=G.next[p])
if(G.to[p]!=pre)
dfs1(G.to[p],pos,dist+G.w[p]);
}
void dfs2(int pos, int pre)
{
ans=max(ans,-a[pos]+segtree.segmax(1,1,N));
for(auto p=G.head[pos];p;p=G.next[p])
if(G.to[p]!=pre)
{
segtree.segadd(1,1,N,-G.w[p]);
segtree.segadd(1,ltid[G.to[p]],rtid[G.to[p]],2*G.w[p]);
dfs2(G.to[p],pos);
segtree.segadd(1,1,N,G.w[p]);
segtree.segadd(1,ltid[G.to[p]],rtid[G.to[p]],-2*G.w[p]);
}
}
int read(int x=0)
{
int c, f(1);
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-48;
return f*x;
}
int main()
{
int T(read()), i;
while(T--)
{
N=read();
G.clear(N);
tim=0;
for(i=1;i<=N;i++)a[i]=read();
for(i=1;i<N;i++)
{
auto u(read()), v(read()), w(read());
G.adde(u,v,w), G.adde(v,u,w);
}
dfs0(1,0);
dfs1(1,0,0);
segtree.build(1,1,N,v);
ans=0;
dfs2(1,0);
cout<<ans<<endl;
}
}