题解
bzoj3999
这题..唉..是道树剖啊
唉有方向啊~唉麻烦啊~
对于x到y的一条路径,必须是后面的最大值减前面的最小值
而树剖会把这一段分开呀
因此,每次向上跳的时候,不能只记录最大值(右子数最大-左子数组小)了,还要记录这一段的最大最小
而且而且,树剖建树是按dfn序建的树,所以,x向上跳的的部分都是反的,因此,我们还要记录反过来的最大值(左子数最大-右子数最小)
然后..因为x->top[x]在树中相当于top[x]->x,所以跳到同一条链后,x->top[x]一段的最大值,应当是反过来的最大值
同理,跳到同一条链以后,也要注意翻转啊转啊转
代码
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 50010
#define inf 0x7fffffff
struct node{int x,y,next;}mp[2*N];
int n,m,num=0,tot=0,d[N],size[N],son[N],fa[N],h[N],top[N],id[N],real[N],a[N];
struct node1{
int l,r,mx,mn,ans,ans1,f;
node1(){ans=mx=ans1=f=0,mn=inf;}
}tree[4*N];
void insert(int x,int y){
mp[++num].x=x;mp[num].y=y;mp[num].next=h[x];h[x]=num;
mp[++num].x=y;mp[num].y=x;mp[num].next=h[y];h[y]=num;
}
void dfs1(int u){
size[u]=1;
for(int i=h[u];i;i=mp[i].next){
int v=mp[i].y;
if(!d[v]){
fa[v]=u;d[v]=d[u]+1;
dfs1(v);size[u]+=size[v];
if(size[son[u]]<size[v]) son[u]=v;
}
}
}
void dfs2(int u,int tp){
top[u]=tp;id[u]=++tot;real[tot]=u;
if(son[u]) dfs2(son[u],tp);
for(int i=h[u];i;i=mp[i].next){
int v=mp[i].y;
if(v!=son[u] && d[v]==d[u]+1) dfs2(v,v);
}
}
void update(int v){
tree[v].mx=max(tree[v<<1].mx,tree[v<<1|1].mx);
tree[v].mn=min(tree[v<<1].mn,tree[v<<1|1].mn);
tree[v].ans=max(tree[v<<1|1].mx-tree[v<<1].mn,max(tree[v<<1].ans,tree[v<<1|1].ans));
tree[v].ans1=max(tree[v<<1].mx-tree[v<<1|1].mn,max(tree[v<<1].ans1,tree[v<<1|1].ans1));
}
void build(int v,int l,int r){
tree[v].l=l;tree[v].r=r;
if(l==r){
tree[v].ans=tree[v].ans1=tree[v].f=0;tree[v].mx=tree[v].mn=a[real[l]];
return ;
}int mid=l+r>>1;
build(v<<1,l,mid);build(v<<1|1,mid+1,r);
update(v);
}
void pushdown(int v){
if(!tree[v].f) return;
tree[v<<1].f+=tree[v].f;tree[v<<1|1].f+=tree[v].f;
tree[v<<1].mx+=tree[v].f;tree[v<<1|1].mx+=tree[v].f;
tree[v<<1].mn+=tree[v].f;tree[v<<1|1].mn+=tree[v].f;
tree[v].f=0;
}
node1 update1(node1 x,node1 y){
node1 z;
z.ans=max(y.mx-x.mn,max(x.ans,y.ans));
z.ans1=max(x.mx-y.mn,max(x.ans1,y.ans1));
z.mn=min(x.mn,y.mn);z.mx=max(x.mx,y.mx);
return z;
}
node1 query(int v,int l,int r,int x){
if(l<=tree[v].l && tree[v].r<=r){
tree[v].f+=x;tree[v].mx+=x;tree[v].mn+=x;
return tree[v];
}int mid=tree[v].l+tree[v].r>>1;node1 s1,s2;pushdown(v);
if(l<=mid) s1=query(v<<1,l,r,x);
if(mid<r) s2=query(v<<1|1,l,r,x);
update(v);return update1(s1,s2);
}
int solve(int x,int y,int z){
node1 ansl,ansr,ans;
while(top[x]!=top[y]){
if(d[top[x]]>=d[top[y]]){
ansl=update1(query(1,id[top[x]],id[x],z),ansl);
x=fa[top[x]];
}else{
ansr=update1(query(1,id[top[y]],id[y],z),ansr);
y=fa[top[y]];
}
}swap(ansl.ans,ansl.ans1);
if(id[x]<=id[y]) ansl=update1(ansl,query(1,id[x],id[y],z));
else{
node1 t=query(1,id[y],id[x],z);swap(t.ans,t.ans1);
ansr=update1(t,ansr);
}ans=update1(ansl,ansr);
return ans.ans;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<n;i++){
int x,y;scanf("%d%d",&x,&y);
insert(x,y);
}d[1]=1;dfs1(1);dfs2(1,1);
build(1,1,n);scanf("%d",&m);
for(int i=1;i<=m;i++){
int x,y,z;scanf("%d%d%d",&x,&y,&z);
printf("%d\n",solve(x,y,z));
}
return 0;
}