http://www.lydsy.com/JudgeOnline/problem.php?id=4034
对于一棵树支持
1:单点修改
2:子树修改
3:单点到根的路径查询
ydc大爷的题解http://ydc.blog.uoj.ac/blog/336
dfs序+线段树
对于操作1,相当于对子树都加上同一个值
对于操作2,相当于对于v的子树都加上 (depu−depv+1)∗x ,我们把它再拆一下就是 depu∗x+(1−depv)∗x ,就分离成立与每个点u的深度有关的部分和无关的部分,分开维护即可
10^6如果是个链显然爆longint,所以……
const
maxn=100005;
var
dep,t:array[0..maxn]of int64;
x:array[0..maxn]of int64;
z:array[0..4*maxn,1..2]of longint;
y:array[0..maxn,1..2]of int64;
w:array[0..6*maxn,1..6]of int64;
i,j,k:longint;
n,m,len:longint;
a,b,c:int64;
head,tail,v,tt:longint;
procedure init(a,b:longint);
begin
z[len,1]:=b;
if z[a,2]=0
then z[a,2]:=len else z[z[a,1],2]:=len;
z[a,1]:=len; inc(len);
end;
procedure deep;
begin
t[1]:=1; head:=1; tail:=2;
while head<tail do
begin
v:=t[head]; tt:=z[v,2]; inc(head);
while tt<>0 do
begin
if dep[z[tt,1]]=0 then begin
dep[z[tt,1]]:=dep[v]+1;
t[tail]:=z[tt,1]; inc(tail);
end;
tt:=z[tt,2];
end;
end;
end;
procedure dfs(a:longint);
var tt:longint;
begin
inc(len); y[a,1]:=len; tt:=z[a,2];
while tt<>0 do
begin
if y[z[tt,1],1]=0 then dfs(z[tt,1]);
tt:=z[tt,2];
end;
y[a,2]:=len;
end;
procedure build(a,l,r:longint);
var mid:longint;
begin
w[a,1]:=l; w[a,2]:=r; w[a,3]:=0; w[a,4]:=0; w[a,5]:=0; w[a,6]:=0;
if l=r then exit;
mid:=(l+r)>>1;
build(a<<1,l,mid); build(a<<1+1,mid+1,r);
end;
procedure pushdown(a:longint);
begin
if w[a,1]=w[a,2] then begin inc(w[a,3],w[a,5]); w[a,5]:=0; inc(w[a,4],w[a,6]); w[a,6]:=0; exit; end;
inc(w[a,3],w[a,5]); inc(w[a,4],w[a,6]);
inc(w[a<<1,5],w[a,5]); inc(w[a<<1+1,5],w[a,5]);
inc(w[a<<1,6],w[a,6]); inc(w[a<<1+1,6],w[a,6]);
w[a,5]:=0; w[a,6]:=0;
end;
procedure update1(a,l,r:longint;c:int64);
var mid:longint;
begin
if (w[a,5]<>0)or(w[a,6]<>0) then pushdown(a);
if (w[a,1]=l)and(w[a,2]=r) then begin inc(w[a,6],c); exit; end;
mid:=(w[a,1]+w[a,2])>>1;
if r<=mid then update1(a<<1,l,r,c) else
if l>mid then update1(a<<1+1,l,r,c)
else begin update1(a<<1,l,mid,c); update1(a<<1+1,mid+1,r,c); end;
end;
procedure update2(a,l,r:longint;b,c:int64);
var mid:longint;
begin
if (w[a,5]<>0)or(w[a,6]<>0) then pushdown(a);
if (w[a,1]=l)and(w[a,2]=r) then begin inc(w[a,5],b); inc(w[a,6],c); exit; end;
mid:=(w[a,1]+w[a,2])>>1;
if r<=mid then update2(a<<1,l,r,b,c) else
if l>mid then update2(a<<1+1,l,r,b,c)
else begin update2(a<<1,l,mid,b,c); update2(a<<1+1,mid+1,r,b,c); end;
end;
function query(a,b:longint;c:int64):int64;
var mid:longint;
begin
if (w[a,5]<>0)or(w[a,6]<>0) then pushdown(a);
if (w[a,1]=w[a,2])and(w[a,1]=b) then exit(w[a,3]*c+w[a,4]);
mid:=(w[a,1]+w[a,2])>>1;
if b<=mid
then exit(query(a<<1,b,c))
else exit(query(a<<1+1,b,c));
end;
begin
readln(n,m); len:=n+1;
for i:=1 to n do
read(x[i]);
for i:=1 to n-1 do
begin
readln(a,b);
init(a,b); init(b,a);
end;
dep[1]:=1; deep;
len:=0; dfs(1);
build(1,1,n);
for i:=1 to n do
update1(1,y[i,1],y[i,2],x[i]);
for i:=1 to m do
begin
read(a);
case a of
1:begin readln(b,c); update1(1,y[b,1],y[b,2],c); end;
2:begin readln(b,c); update2(1,y[b,1],y[b,2],c,(1-dep[b])*c); end;
3:begin readln(b); writeln(query(1,y[b,1],dep[b])); end;
end;
end;
end.