11
29
2015
0

[bzoj 4034][HAOI2015]T2

 有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个

操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

这是我A的第二道树链剖分,A第一道在4个月前。

 

http://blog.sina.com.cn/s/blog_7a1746820100wp67.html

http://www.tuicool.com/articles/mQB36z

这俩教程不错。

 

因为以X为根中的子树分成了一条条重链,而他们的编号是连续的。

所以我们可以在DFS2时找到以x为根时它的子树在线段树中的最大编号mx[x]。

然后就是裸地区间修改和求和。

这LCA都不用。

记得大数据题要写成t[p].s:=t[p].s*(r-l+1)*v,v:int64(WA*N)

 

var t:array[1..500000]of record
                             a,s:int64;
                            end;
    head,vet,next,top,tid,mx,fa,size,a:array[0..200000]of longint;
    n,m,i,x,y,tot,time,ch:longint;

procedure add(a,b:longint);
begin
 inc(tot);
 next[tot]:=head[a];
 vet[tot]:=b;
 head[a]:=tot;
end;

function max(x,y:longint):longint;
begin
 if x>y then exit(x);
 exit(y);
end;

function min(x,y:longint):longint;
begin
 if x<y then exit(X);
 exit(y);
end;

procedure dfs1(u:longint);
var e,v:longint;
begin
 size[u]:=1;
 e:=head[u];
 while e<>0 do
 begin
  v:=vet[e];
  if v<>fa[u] then
  begin
   fa[v]:=u;
   dfs1(v);
   size[u]:=size[u]+size[v];
   mx[u]:=max(mx[u],mx[v]);
  end;
  e:=next[e];
 end;
end;

procedure dfs2(u,ance:longint);
var e,v,k:longint;
begin
 inc(time); tid[u]:=time; top[u]:=ance; mx[u]:=time;
 e:=head[u];
 k:=0;
 while e<>0 do
 begin
  v:=vet[e];
  if (v<>fa[u])and(size[v]>size[k]) then k:=v;
  e:=next[e];
 end;
 if k>0 then
 begin
  dfs2(k,ance);
  mx[u]:=max(mx[u],mx[k]);
 end;
 e:=head[u];
 while e<>0 do
 begin
  v:=vet[e];
  if (v<>fa[u])and(v<>k) then
  begin
   dfs2(v,v);
   mx[u]:=max(mx[u],mx[v]);
  end;
  e:=next[e];
 end;
end;

procedure pushdown(l,r,p:longint);
var mid,ls,rs:longint;
begin
 if l=r then exit;
 mid:=(l+r)>>1;
 ls:=p<<1; rs:=ls+1;
 t[ls].a:=t[ls].a+t[p].a;
 t[rs].a:=t[rs].a+t[p].a;
 t[ls].s:=t[ls].s+(mid-l+1)*t[p].a;
 t[rs].s:=t[rs].s+(r-mid)*t[p].a;
 t[p].a:=0;
end;

function query(l,r,x,y,p:longint):int64;
var mid:longint;
begin
 if (l>=x)and(r<=y) then exit(t[p].s);
 pushdown(l,r,p);
 mid:=(l+r)>>1;
 query:=0;
 if x<=mid then query:=query+query(l,mid,x,y,p<<1);
 if y>mid then query:=query+query(mid+1,r,x,y,p<<1+1);
end;

function querys(x:longint):int64;
begin
 querys:=0;
 while top[x]<>1 do
 begin
  querys:=querys+query(1,n,tid[top[x]],tid[x],1);
  x:=fa[top[x]];
 end;
 querys:=querys+query(1,n,1,tid[x],1);
end;

procedure update(l,r,x,y:longint;v:int64;p:longint);
var mid:longint;
begin
 if (l>=x)and(r<=y) then
 begin
  t[p].a:=t[p].a+v;
  t[p].s:=t[p].s+v*(r-l+1);
  exit;
 end;
 pushdown(l,r,p);
 mid:=(l+r)>>1;
 if x<=mid then update(l,mid,x,y,v,p<<1);
 if y>mid then update(mid+1,r,x,y,v,p<<1+1);
 t[p].s:=t[p<<1].s+t[p<<1+1].s;
end;


begin
 assign(input,'1.in'); reset(input);
 assign(output,'1.out'); rewrite(output);
 read(n,m);
 for i:=1 to n do read(a[i]);
 for i:=1 to n-1 do
 begin
  read(x,y);
  add(x,y);
  add(y,x);
 end;
 dfs1(1);
 dfs2(1,1);
 for i:=1 to n do update(1,n,tid[i],tid[i],a[i],1);

 for i:=1 to m do
 begin
  read(ch);
  case ch of
   1:
   begin
    read(x,y);
    update(1,n,tid[x],tid[x],y,1);
   end;
   2:
   begin
    read(x,y);
    update(1,n,tid[x],mx[x],y,1);
   end;
   3:
   begin
    read(x);
    writeln(querys(x));
   end;
  end;
 end;

 close(input);
 close(output);
end.

 

Category: 树链剖分 | Tags: | Read Count: 335

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com