80%:做不出100%,先来个80分水法
首先将x,y之间有边的记录两个,存在a数组里,一个是x,y,另一个是y,x
然后将这个a数组排序,将a[i,1]按升序排序。
Then 就可以求出每一个点与多少个点有边,求出每一个点的"子点"的区间,用l和r数组存
再用dfs求出以1作根,每一个点的father是谁
预处理Over
如果为1,新建一个数组k来存它们的变化;
如果为2,就从这个点往回推,如果为偶数次就+k[j],如果为奇数次就-k[j],j=father[j]
80%代码:
var a:array[0..200000,1..2]of longint;
father,l,r,k,d:array[0..100000]of longint;
v:array[0..100000]of boolean;
n,m,i,j,z,y,x,w:longint;
procedure qsort(l,r:longint);
var i,j,mid:longint;
begin
if l>=r then exit;
i:=l; j:=r; mid:=a[(l+r) div 2,1];
repeat
while a[i,1]<mid do inc(i);
while a[j,1]>mid do dec(j);
if i<=j then
begin
a[0]:=a[i];a[i]:=a[j];a[j]:=a[0];
inc(i);dec(j);
end;
until i>j;
qsort(i,r);
qsort(l,j);
end;
procedure find_father(x:longint);
var i:longint;
begin
v[x]:=false;
for i:=l[x] to r[x] do
if v[a[i,2]]=true then
begin
father[a[i,2]]:=x;
find_father(a[i,2]);
end;
end;
begin
readln(n,m);
for i:=1 to n do read(d[i]);
readln;
for i:=1 to n-1 do
begin
readln(x,y);
a[i*2-1,1]:=x;
a[i*2-1,2]:=y;
a[i*2,1]:=y;
a[i*2,2]:=x;
end;
qsort(1,(n-1)*2);
for i:=1 to (n-1)*2 do
begin
if a[i,1]<>a[i-1,1] then l[a[i,1]]:=i;
if a[i,1]<>a[i+1,1] then r[a[i,1]]:=i;
end;
fillchar(v,sizeof(v),true);
find_father(1);
for i:=1 to m do
begin
read(x);
if x=1 then
begin
readln(j,y);
k[j]:=k[j]+y;
end;
if x=2 then
begin
readln(w);
j:=w;y:=0;z:=d[w];
while j<>0 do
begin
y:=1-y;
if y=0 then z:=z-k[j] else z:=z+k[j];
j:=father[j];
end;
writeln(z);
end;
end;
end.