很直接的一个想法就是把的作为断点,将整个链切分为两段。
那么只有三种情况:
在买卖
在买卖
在买,在卖
求就交给了倍增,因为树剖后面还要写数据结构维护,比较麻烦。。。
(当然离线也可做)
维护四个值:
前两个很显然的维护方式,跟着倍增一起跳就好。
后面两个维护是和求解方式差不多的思路,也就是把拆成,仍然是上述三种情况。
这样维护的式子就出来了:()
最终答案的式子同理。
防止溢出建议开。
附代码:
#include<iostream> #include<algorithm> #include<cstdio> #define MAXN 50010 #define MAX (1LL<<62) using namespace std; int n,q,c=1; int head[MAXN],deep[MAXN],f[MAXN][20]; long long val[MAXN],maxn[MAXN][20],minn[MAXN][20],upon[MAXN][20],down[MAXN][20]; struct Tree{ int next,to; }tree[MAXN<<1]; char tp[100000],*p1=tp,*p2=tp; inline char get_char(){ return p1==p2&&(p2=(p1=tp)+fread(tp,1,100000,stdin),p1==p2)?EOF:*p1++; } inline int read(){ int date=0,w=1;char c=0; while(c<'0'||c>'9'){if(c=='-')w=-1;c=get_char();} while(c>='0'&&c<='9'){date=date*10+c-'0';c=get_char();} return date*w; } inline void addedge(int x,int y){ tree[c].to=y;tree[c].next=head[x];head[x]=c++; tree[c].to=x;tree[c].next=head[y];head[y]=c++; } void dfs(int rt){ for(int i=head[rt],will;i;i=tree[i].next){ will=tree[i].to; if(!deep[will]){ deep[will]=deep[rt]+1; f[will][0]=rt; maxn[will][0]=max(val[rt],val[will]); minn[will][0]=min(val[rt],val[will]); upon[will][0]=max(val[rt]-val[will],0LL); down[will][0]=max(val[will]-val[rt],0LL); dfs(will); } } } void step(){ for(int j=1;j<=19;j++)for(int i=1,k;i<=n;i++){ f[i][j]=f[f[i][j-1]][j-1]; k=f[i][j-1]; maxn[i][j]=max(maxn[i][j-1],maxn[k][j-1]); minn[i][j]=min(minn[i][j-1],minn[k][j-1]); upon[i][j]=max(maxn[k][j-1]-minn[i][j-1],max(upon[i][j-1],upon[k][j-1])); down[i][j]=max(maxn[i][j-1]-minn[k][j-1],max(down[i][j-1],down[k][j-1])); } } int LCA(int x,int y){ if(deep[x]<deep[y])swap(x,y); for(int i=19;i>=0;i--)if(deep[f[x][i]]>=deep[y])x=f[x][i]; if(x==y)return x; for(int i=19;i>=0;i--)if(f[x][i]!=f[y][i]){x=f[x][i];y=f[y][i];} return f[x][0]; } long long query(int x,int y,int lca){ long long front=MAX,after=0,s=0; for(int i=19;i>=0;i--){ if((deep[x]-deep[lca])&(1<<i)){ s=max(s,max(upon[x][i],maxn[x][i]-front)); front=min(front,minn[x][i]); x=f[x][i]; } if((deep[y]-deep[lca])&(1<<i)){ s=max(s,max(down[y][i],after-minn[y][i])); after=max(after,maxn[y][i]); y=f[y][i]; } } return 1LL*max(s,after-front); } void work(){ int x,y,lca; q=read(); while(q--){ x=read();y=read(); lca=LCA(x,y); printf("%lld\n",query(x,y,lca)); } } void init(){ n=read(); for(int i=1;i<=n;i++)val[i]=read(); for(int i=1,x,y;i<n;i++){ x=read();y=read(); addedge(x,y); } deep[1]=1; dfs(1); step(); } int main(){ init(); work(); return 0; }