题意:对一棵n个节点且每个节点初始值都为0的树,进行两个操作:
1、Add x y z 表示x到y的路径上的点的点权都+z
2、Query x 表示询问以x为根的子树的点权和
树链剖分裸题,mdzz,8A....
对于修改x到y的路径上的点的点权,注意x到y并不是一段连续的区间,需要跳到同一条链上才能用线段树进行区间修改
对于查询,由于以x为根的子树在线段树中是一段连续的区间[num[x],num[x]+size[x]-1],并不需要把左右端点跳到同一条链上,不然会多算...(mdzz,当时没多想,直接复制的wawawa....= =)
type
rec=record
l,r:longint;
sum,lazy:int64;
end;
var
n,m,l,x,y,z,tot :longint;
i :longint;
ch :char;
s :string;
last,num,father :array[0..100010] of longint;
size,max_son,d,top :array[0..100010] of longint;
vis :array[0..100010] of boolean;
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]]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 exit;
mid:=(l+r)>>1;
build(2*x,l,mid); build(2*x+1,mid+1,r);
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,z:longint);
var
mid:longint;
begin
if (t[x].l=l) and (t[x].r=r) then
begin
inc(t[x].lazy,z);exit;
end;
if (t[x].lazy<>0) then update(x);
mid:=(t[x].l+t[x].r) >>1;
if (r<=mid) then change(x*2,l,r,z) else
if (l>mid) then change(2*x+1,l,r,z) else
begin
change(2*x,l,mid,z);
change(2*x+1,mid+1,r,z);
end;
t[x].sum:=t[2*x+1].sum+t[2*x].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 change1(x,y,z:longint);
var
c:longint;
begin
if d[x]>d[y] then
begin
c:=x; x:=y; y:=c;
end;
while (d[x]top[y]) do
begin
change(1,num[top[y]],num[y],z);
change(1,num[top[x]],num[x],z);
x:=father[top[x]];
y:=father[top[y]];
end;
if num[x]' ') do
begin
s:=s+ch;
read(ch);
end;
if (s='Add') then
begin
readln(x,y,z);
inc(x); inc(y);
change1(x,y,z);
end else
begin
readln(x);
inc(x);
writeln(get_sum(1,num[x],num[x]+size[x]-1));
end;
end;
end.
——by Eirlys