思路: 在线段树节点中维护四个值,1.maxx , 2. minn, 3 .best0 4 best1 分别表示当前区间的最大值 ,最小值,从线段树左子树向右子树走的最大盈利和右子树向左子树走的最大盈利,然后就是在x向y走的时候根据当前是x跳到父节点还是y调到父节点来改变方向,在跳的过程中维护4个变量,maxu ,minu ,maxv , minv 和 两个临时变量, 分别表示 x已经走过的最大值和最小值, y已经走过的最大值和最小值,和当前(刚刚) x(或者y ) 跳过的最大最小值。 答案就很明显了。 1 跳过的一段的best 2,2.best=max(best,tmpmx-minu); 3. best=max(best,maxv-tmpmn); 4. best=max(best,tmpmx-minu); 5.best=max(best,maxv-tmpmn);
代码:
#include<bits/stdc++.h>
#define lson (i<<1)
#define rson (i<<1|1)
using namespace std;
typedef long long ll;
const ll inf=1e18+5;
const int N =5e4+5;
struct eee
{
int v;
int next;
}edge[N*2];
int tot,head[N];
struct node
{
int l,r;
ll mx,mn;
ll best0,best1;
ll lz;
}tr[N<<2];
int fat[N];
int dep[N];
int siz[N];
int son[N];
int rak[N];
int top[N];
int idd[N];
int cnt;
int n,m,r;
ll a[N];
void init()
{
tot=0;
cnt=0;
for(int i=0;i<=n;i++){
head[i]=-1;
son[i]=0;
siz[i]=0;
}
}
void add(int u,int v)
{
edge[++tot].v=v; edge[tot].next=head[u]; head[u]=tot;
}
void dfs1(int u,int fa,int deep)
{
fat[u]=fa;
dep[u]=deep;
siz[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v==fa) continue;
dfs1(v,u,deep+1);
siz[u]+=siz[v];
if(son[u]==0||siz[v]>siz[son[u]]){
son[u]=v;
}
}
}
void dfs2(int u,int t)
{
top[u]=t;
idd[u]=++cnt;
rak[cnt]=u;
if(!son[u]) return ;
dfs2(son[u],t);
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v!=son[u]&&v!=fat[u]){
dfs2(v,v);
}
}
}
void push_up(int i)
{
tr[i].mn=min(tr[lson].mn,tr[rson].mn);
tr[i].mx=max(tr[lson].mx,tr[rson].mx);
tr[i].best0=max(tr[lson].best0,tr[rson].best0);
tr[i].best1=max(tr[lson].best1,tr[rson].best1);
tr[i].best0=max(tr[i].best0,tr[rson].mx-tr[lson].mn);
tr[i].best1=max(tr[i].best1,tr[lson].mx-tr[rson].mn);
}
void push_down(int i)
{
ll &lz=tr[i].lz;
if(lz)
{
tr[lson].mx+=lz; tr[lson].mn+=lz; tr[lson].lz+=lz;
tr[rson].mx+=lz; tr[rson].mn+=lz; tr[rson].lz+=lz;
lz=0;
}
}
void build(int i,int l,int r)
{
tr[i].l=l; tr[i].r=r; tr[i].best0=tr[i].best1=0;
tr[i].mx=0; tr[i].mn=inf; tr[i].lz=0;
if(l==r){
tr[i].mn=tr[i].mx=a[rak[l]];
return ;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
push_up(i);
}
void update(int i,int l,int r,ll val)
{
if(tr[i].l==l&&tr[i].r==r){
tr[i].lz+=val;
tr[i].mx+=val;
tr[i].mn+=val;
return ;
}
push_down(i);
int mid=(tr[i].l+tr[i].r)>>1;
if(r<=mid) update(lson,l,r,val);
else if(l>mid) update(rson,l,r,val);
else{
update(lson,l,mid,val);
update(rson,mid+1,r,val);
}
push_up(i);
}
ll query(int i,int l,int r,int dir,ll &mx,ll &mn)
{
if(tr[i].l==l&&tr[i].r==r){
mx=max(tr[i].mx,mx);
mn=min(tr[i].mn,mn);
if(dir==0) return tr[i].best0;
else return tr[i].best1;
}
push_down(i);
int mid=(tr[i].l+tr[i].r)>>1;
if(r<=mid) return query(lson,l,r,dir,mx,mn);
else if(l>mid) return query(rson,l,r,dir,mx,mn);
else{
ll mx1,mx2,mn1,mn2,best;
mx1=mx2=best=0; mn1=mn2=inf;
ll tmpl=query(lson,l,mid,dir,mx1,mn1);
ll tmpr=query(rson,mid+1,r,dir,mx2,mn2);
mx=max(mx1,mx2); mn=min(mn1,mn2);
best=max(tmpl,tmpr);
if(dir==0) best=max(best,mx2-mn1);
else best=max(best,mx1-mn2);
return best;
}
}
ll querys(int x,int y,ll val)
{
ll best=0;
int fx=top[x]; int fy=top[y];
ll maxu,minu,maxv,minv;
maxu=maxv=0;
minu=minv=inf;
ll tmpmx,tmpmn;
while(fx!=fy)
{
if(dep[fx]>=dep[fy]){
tmpmx=0; tmpmn=inf;
best=max(best,query(1,idd[fx],idd[x],1,tmpmx,tmpmn));
best=max(best,tmpmx-minu);
best=max(best,maxv-tmpmn);
//cout<<"** tmpmx "<<tmpmx<<" tmpmn "<<tmpmn<<endl;
maxu=max(maxu,tmpmx);
minu=min(minu,tmpmn);
update(1,idd[fx],idd[x],val);
x=fat[fx]; fx=top[x];
}
else{
tmpmx=0; tmpmn=inf;
best=max(best,query(1,idd[fy],idd[y],0,tmpmx,tmpmn));
best=max(best,tmpmx-minu);
best=max(best,maxv-tmpmn);
//cout<<"tmpmx "<<tmpmx<<" tmpmn "<<tmpmn<<endl;
maxv=max(maxv,tmpmx);
minv=min(minv,tmpmn);
//cout<<"yyyy"<<endl;
update(1,idd[fy],idd[y],val);
//cout<<"lalal"<<endl;
y=fat[fy]; fy=top[y];
}
}
if(idd[x]<=idd[y]){
tmpmx=0; tmpmn=inf;
best=max(best,query(1,idd[x],idd[y],0,tmpmx,tmpmn));
best=max(best,tmpmx-minu);
best=max(best,maxv-tmpmn);
update(1,idd[x],idd[y],val);
//cout<<"lalal"<<endl;
}
else{
tmpmx=0; tmpmn=inf;
best=max(best,query(1,idd[y],idd[x],1,tmpmx,tmpmn));
best=max(best,tmpmx-minu);
best=max(best,maxv-tmpmn);
//cout<<"tmpmx "<<tmpmx<<" tmpmn "<<tmpmn<<endl;
update(1,idd[y],idd[x],val);
}
return best;
}
int main()
{
int T,q;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
init();
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
int u,v;
for(int i=1;i<n;i++){
scanf("%d %d",&u,&v);
add(u,v);
add(v,u);
}
dfs1(1,1,0);
dfs2(1,1);
build(1,1,n);
/*
for(int i=1;i<=n;i++){
cout<<"*** fat "<<fat[i]<<" dep "<<dep[i]<<" siz "<<siz[i]<<" son "<<son[i]<<" rak "<<rak[i]<<" top "<<top[i]<<" idd "<<idd[i]<<endl;
}
*/
scanf("%d",&q);
ll val;
while(q--)
{
scanf("%d %d %lld",&u,&v,&val);
ll ans=querys(u,v,val);
printf("%lld\n",ans);
}
}
return 0;
}