链剖裸题。只不过码量很大。注意细节就好。
答案分三种情况:在起点到lca之间;在lca到终点之间;在lca两侧。
之前犯了一个错误:求一个区间内部的极差的时候求错了
int shang(int root,int l,int r){
if(T[root].l>=l&&T[root].r<=r)
return T[root].ansl;
pushdown(root);
int ret=0;
if(l<=mid) ret=max(ret,shang(lc,l,r));
if(r> mid) ret=max(ret,shang(rc,l,r));
return ret;
}
int xia(int root,int l,int r){
if(T[root].l>=l&&T[root].r<=r)
return T[root].ansr;
pushdown(root);
int ret=0;
if(l<=mid) ret=max(ret,xia(lc,l,r));
if(r> mid) ret=max(ret,xia(rc,l,r));
return ret;
}
这里应该用线段树合并!!
#include<bits/stdc++.h>
#define mid ((T[root].l+T[root].r)>>1)
#define lc (root<<1)
#define rc (root<<1|1)
using namespace std;
const int maxn=5e4+10;
const int oo=1<<30;
int Head[maxn],Next[maxn<<1],V[maxn<<1],cnt=0;
int t[maxn],dfn[maxn],son[maxn],siz[maxn],dep[maxn],tp[maxn],fa[maxn],tot=0;
int n,q,val[maxn],x,y,v;
struct node{
int l,r,lz,mx,mn,ansl,ansr;
node(){lz=mx=ansl=ansr=0;mn=oo;}
}T[maxn<<2];
inline void add(int u,int v){
++cnt;
Next[cnt]=Head[u];
V[cnt]=v;
Head[u]=cnt;
}
inline int read(){
int x=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x;
}
void dfs1(int u,int f){
son[u]=0,siz[u]=1,fa[u]=f,dep[u]=dep[f]+1;
for(int i=Head[u];i;i=Next[i]) if(V[i]!=f){
dfs1(V[i],u);
siz[u]+=siz[V[i]];
if(siz[V[i]]>siz[son[u]]) son[u]=V[i];
}
}
void dfs2(int u,int top){
t[dfn[u]=++tot]=u,tp[u]=top;
if(son[u]) dfs2(son[u],top);
for(int i=Head[u];i;i=Next[i])
if(V[i]!=fa[u]&&V[i]!=son[u])
dfs2(V[i],V[i]);
}
inline void pushup(int root){
T[root].mx=max(T[lc].mx,T[rc].mx),T[root].mn=min(T[lc].mn,T[rc].mn);
T[root].ansl=max(max(T[lc].ansl,T[rc].ansl),T[lc].mx-T[rc].mn);
T[root].ansr=max(max(T[lc].ansr,T[rc].ansr),T[rc].mx-T[lc].mn);
}
inline void pushnow(int root,int v){T[root].mx+=v,T[root].mn+=v,T[root].lz+=v;}
inline void pushdown(int root){if(T[root].lz) pushnow(lc,T[root].lz),pushnow(rc,T[root].lz),T[root].lz=0;}
void build(int root,int l,int r){
T[root].l=l,T[root].r=r;
if(l==r){T[root].mx=T[root].mn=val[t[l]];return;}
build(lc,l,mid),build(rc,mid+1,r);
pushup(root);
}
void change(int root,int l,int r,int v){
if(T[root].l>=l&&T[root].r<=r){
pushnow(root,v);
return;
}
pushdown(root);
if(l<=mid) change(lc,l,r,v);
if(r> mid) change(rc,l,r,v);
pushup(root);
}
void update(int x,int y,int w){
while(tp[x]!=tp[y]){
if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
change(1,dfn[tp[x]],dfn[x],w);
x=fa[tp[x]];
}
if(dep[x]<dep[y]) swap(x,y);
change(1,dfn[y],dfn[x],w);
}
node Merge(node p1,node p2){
node ret;
ret.mx=max(p1.mx,p2.mx),ret.mn=min(p1.mn,p2.mn);
ret.ansl=max(max(p1.ansl,p2.ansl),p1.mx-p2.mn);//start->lca
ret.ansr=max(max(p1.ansr,p2.ansr),p2.mx-p1.mn);//end->lca
return ret;
}
node get(int root,int l,int r){
if(T[root].l>=l&&T[root].r<=r)
return T[root];
pushdown(root);
if(l>mid) return get(rc,l,r);
if(r<=mid) return get(lc,l,r);
return Merge(get(lc,l,r),get(rc,l,r));
}
int getlca(int x,int y){
while(tp[x]!=tp[y]){
if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
x=fa[tp[x]];
}
if(dep[x]<dep[y]) swap(x,y);
return y;
}
int query(int x,int y){
int g=getlca(x,y);
node L,R;
while(tp[x]!=tp[g]) L=Merge(get(1,dfn[tp[x]],dfn[x]),L),x=fa[tp[x]];
L=Merge(get(1,dfn[g],dfn[x]),L);
while(tp[y]!=tp[g]) R=Merge(get(1,dfn[tp[y]],dfn[y]),R),y=fa[tp[y]];
R=Merge(get(1,dfn[g],dfn[y]),R);
return max(max(L.ansl,R.ansr),R.mx-L.mn);
}
inline void print(int x){
if(x>9) print(x/10);
putchar(x%10+'0');
}
int main(){
n=read();
for(int i=1;i<=n;++i) val[i]=read();
for(int i=1;i<n;++i) x=read(),y=read(),add(x,y),add(y,x);
dfs1(1,0),dfs2(1,1),build(1,1,tot);
q=read();
while(q--){
x=read(),y=read(),v=read();
print(query(x,y)),putchar('\n');
update(x,y,v);
}
}