题意:有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
mdzz,居然没有1A,把点权和边权的弄混了...点权的最后更新的时候是可以num[x]=num[y]的
type
rec=record
l,r:longint;
lazy,sum:int64;
end;
var
n,m,x,y,z,l,tot :longint;
i :longint;
vis :array[0..100010] of boolean;
last,top,d,num :array[0..100010] of longint;
a,w,father :array[0..100010] of longint;
max_son,size :array[0..100010] of longint;
pre,other :array[0..200010] of longint;
t :array[0..400010] of rec;
procedure connect(x,y:longint);
begin
inc(l);
pre[l]:=last[x];
last[x]:=l;
other[l]:=y;
end;
procedure dfs(x:longint);
var
p,q:longint;
begin
size[x]:=1;
q:=last[x];
while (q<>0) do
begin
p:=other[q];
if not vis[p] then
begin
vis[p]:=true;
father[p]:=x;
dfs(p);
inc(size[x],size[p]);
if size[max_son[x]]<size[p] then max_son[x]:=p;
end;
q:=pre[q];
end;
end;
procedure make(x,t,depth:longint);
var
p,q:longint;
begin
inc(tot);
a[tot]:=w[x];
num[x]:=tot;
top[x]:=t;
d[x]:=depth;
if max_son[x]<>0 then
begin
vis[max_son[x]]:=true;
make(max_son[x],t,depth);
end;
q:=last[x];
while (q<>0) do
begin
p:=other[q];
if not vis[p] and (p<>max_son[x]) then
begin
vis[p]:=true;
make(p,p,depth+1);
end;
q:=pre[q];
end;
end;
procedure build(x,l,r:longint);
var
mid:longint;
begin
t[x].l:=l; t[x].r:=r;
if l=r then
begin
t[x].sum:=a[l];exit;
end;
mid:=(l+r)>>1;
build(2*x,l,mid);
build(2*x+1,mid+1,r);
t[x].sum:=t[2*x].sum+t[2*x+1].sum;
end;
procedure update(x:longint);
begin
inc(t[x].sum,t[x].lazy*int64(t[x].r-t[x].l+1));
if t[x].l=t[x].r then
begin
t[x].lazy:=0;exit;
end;
inc(t[2*x].lazy,t[x].lazy);
inc(t[2*x+1].lazy,t[x].lazy);
t[x].lazy:=0;
end;
procedure change(x,l,r,y:longint);
var
mid:longint;
begin
if (t[x].l=l) and (t[x].r=r) then
begin
inc(t[x].lazy,y);exit;
end;
if t[x].lazy<>0 then update(x);
mid:=(t[x].l+t[x].r)>>1;
if (r<=mid) then change(2*x,l,r,y) else
if (l>mid) then change(2*x+1,l,r,y) else
begin
change(2*x,l,mid,y);
change(2*x+1,mid+1,r,y);
end;
t[x].sum:=t[2*x].sum+t[2*x+1].sum
+t[2*x].lazy*int64(t[2*x].r-t[2*x].l+1)
+t[2*x+1].lazy*int64(t[2*x+1].r-t[2*x+1].l+1);
end;
function get_sum(x,l,r:longint):int64;
var
mid:longint;
begin
if t[x].lazy<>0 then update(x);
if (t[x].l=l) and (t[x].r=r) then exit(t[x].sum);
mid:=(t[x].l+t[x].r)>>1;
if (r<=mid) then exit(get_sum(2*x,l,r)) else
if (l>mid) then exit(get_sum(2*x+1,l,r)) else
exit(get_sum(2*x,l,mid)+get_sum(2*x+1,mid+1,r));
end;
procedure query(x,y:longint);
var
ans:int64;
begin
ans:=0;
while (d[x]<d[y]) do
begin
inc(ans,get_sum(1,num[top[y]],num[y]));
y:=father[top[y]];
end;
while (top[x]<>top[y]) do
begin
inc(ans,get_sum(1,num[top[x]],num[x]));
inc(ans,get_sum(1,num[top[y]],num[y]));
x:=father[top[x]];
y:=father[top[y]];
end;
if num[x]<num[y] then inc(ans,get_sum(1,num[x],num[y]))
else inc(ans,get_sum(1,num[y],num[x]));
writeln(ans);
end;
begin
read(n,m);
for i:=1 to n do read(w[i]);
for i:=1 to n-1 do
begin
reaD(x,y);
connect(x,y);
connect(y,x);
end;
vis[1]:=true; dfs(1);
fillchar(vis,sizeof(vis),false);
vis[1]:=true; make(1,1,1);
build(1,1,n);
for i:=1 to m do
begin
read(x);
if x=1 then
begin
read(y,z);
change(1,num[y],num[y],z);
end else
if x=2 then
begin
read(y,z);
change(1,num[y],num[y]+size[y]-1,z);
end else
begin
read(y);
query(1,y);
end;
end;
end.
——by Eirlys