bzoj 4034 树链剖分模板

来源:互联网 发布:libsvm c语言 使用 编辑:程序博客网 时间:2024/06/05 06:21

题意:有一棵点数为 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



0 0
原创粉丝点击