题目描述
JIH的玩具厂设立以来,发展了一张销售关系网。这张网以玩具厂为总代理(根),构成一颗树。每个节点都代表一个客户,且每个节点都有重要度ai。JIH想将这些客户划成若干类别,当然同一类的客户重要度相差太大总是不妥。所以JIH决定先进行市场调研。JIH会选择两个客户X,从X向根走一共k个节点进行调查。调查的结果是这条路径上重要程度相差最大的两个客户的差值是多少。因为特殊需要,要求重要度大的客户必须在重要度小的客户后面(顺序为X到根,若序列为递减,则输出0,详情见样例)。
输入
第一行一个整数N 表示N个客户
第二行N个整数Ai 表示N个客户的重要程度(工厂是1)
第三行开始 共N-1行 每行2个整数 x,y 表示x的父亲是y
接着一行一个正整数Q,表示Q次调研
接着Q行,每行两个整数X,K。含义见题目表述。
输出
Q行,每行一个正整数,含义见题目描述。
样例输入
6
5 6 1 7 5 2
2 1
3 1
4 2
5 2
6 3
3
4 3
6 2
6 3
样例输出
0
0
4
提示
数据范围:
30% 的数据中N,Q<=1000
100%的数据中N,Q<=200000 Ai<=1000000
对于树上路径问题,我们采用倍增思想,记gmin[i,k],gmax[i,k],gans[i,k]分别表示i到i的2^k个父亲的最小值,最大值,与答案。对于答案的计算,对于预处理:
gans[i,k]:=max(gans[i,k-1],gans[f[i,k-1],k-1]);
gans[i,k]:=max(gans[i,k],gmax[f[i,k-1],k-1]-gmin[i,k-1]);
答案可能为两段答案的最大值,或者一段的最大值减另一段的最小值。
对于询问:
ans:=max(maxn-mini,max(gans[i,k],gans[j,k]));
答案可以是i到i+2^k这一段的gans,或j到j+2^k段的答案,或是i+2^k到j+2^k段的最大值-i到j段的最小值。
var
a:array[0..200022] of longint;
f,gmax,gmin,gans:array[0..200002,0..18] of longint;
n,i,u,v,k,q,x,r,jump,ans,mini,maxn,d:longint;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
begin
readln(n);
for i:=1 to n do
read(a[i]);
readln;
for i:=1 to n-1 do
begin
readln(v,u);
f[v,0]:=u;
gmax[v,0]:=max(a[v],a[u]);
gmin[v,0]:=min(a[v],a[u]);
gans[v,0]:=max(0,a[u]-a[v]);
end;
gmax[1,0]:=a[1];
gmin[1,0]:=a[1];
for k:=1 to 18 do
begin
for i:=1 to n do
begin
f[i,k]:=f[f[i,k-1],k-1];
gmax[i,k]:=max(gmax[i,k-1],gmax[f[i,k-1],k-1]);
gmin[i,k]:=min(gmin[i,k-1],gmin[f[i,k-1],k-1]);
gans[i,k]:=max(gans[i,k-1],gans[f[i,k-1],k-1]);
gans[i,k]:=max(gans[i,k],gmax[f[i,k-1],k-1]-gmin[i,k-1]);
end;
end;
readln(q);
for i:=1 to q do
begin
readln(u,x);
x:=x-1;
r:=0;
for k:=18 downto 0 do
if x>>k and 1=1 then begin r:=1<<k; break; end;
ans:=0;
jump:=x-r;
v:=u;
mini:=maxlongint;
for d:=0 to 18 do
if jump>>d and 1=1 then begin mini:=min(mini,gmin[v,d]); v:=f[v,d]; end;
ans:=max(gans[u,k],gans[v,k]);
v:=f[u,k];
maxn:=0;
for d:=0 to 18 do
if jump>>d and 1=1 then begin maxn:=max(maxn,gmax[v,d]); v:=f[v,d]; end;
ans:=max(maxn-mini,ans);
writeln(ans);
end;
end.