【BZOJ4034】T2(树链剖分)

题意:

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

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

对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不


会超过 10^6。
 
思路:

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

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

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

 

  1 var t:array[1..500000]of record
  2                           a,s:int64;
  3                          end;
  4     head,vet,next,top,tid,mx,fa,size,a,son,flag,dep,id:array[0..200000]of longint;
  5     n,m,i,x,y,tot,time,ch:longint;
  6 
  7 procedure add(a,b:longint);
  8 begin
  9  inc(tot);
 10  next[tot]:=head[a];
 11  vet[tot]:=b;
 12  head[a]:=tot;
 13 end;
 14 
 15 function max(x,y:longint):longint;
 16 begin
 17  if x>y then exit(x);
 18  exit(y);
 19 end;
 20 
 21 procedure dfs1(u:longint);
 22 var e,maxsize,v:longint;
 23 begin
 24  flag[u]:=1; size[u]:=1;
 25  e:=head[u]; son[u]:=0; maxsize:=0;
 26  while e<>0 do
 27  begin
 28   v:=vet[e];
 29   if flag[v]=0 then
 30   begin
 31    fa[v]:=u; dep[v]:=dep[u]+1;
 32    dfs1(v);
 33    size[u]:=size[u]+size[v];
 34    if size[v]>maxsize then
 35    begin
 36     maxsize:=size[v];
 37     son[u]:=v;
 38    end;
 39   end;
 40   e:=next[e];
 41  end;
 42 end;
 43 
 44 procedure dfs2(u,ance:longint);
 45 var e,v:longint;
 46 begin
 47  flag[u]:=1; inc(time); tid[u]:=time; id[time]:=u; top[u]:=ance;
 48  mx[u]:=time;
 49  if son[u]>0 then
 50  begin
 51   dfs2(son[u],ance);
 52   mx[u]:=max(mx[u],mx[son[u]]);
 53  end;
 54  e:=head[u];
 55  while e<>0 do
 56  begin
 57   v:=vet[e];
 58   if flag[v]=0 then
 59   begin
 60    dfs2(v,v);
 61    mx[u]:=max(mx[u],mx[v]);
 62   end;
 63   e:=next[e];
 64  end;
 65 end;
 66 
 67 procedure build(l,r,p:longint);
 68 var mid:longint;
 69 begin
 70  if l=r then
 71  begin
 72   t[p].s:=a[id[l]];
 73   exit;
 74  end;
 75  mid:=(l+r)>>1;
 76  build(l,mid,p<<1);
 77  build(mid+1,r,p<<1+1);
 78  t[p].s:=t[p<<1].s+t[p<<1+1].s;
 79 end;
 80 
 81 procedure update(l,r,x,y:longint;v:int64;p:longint);
 82 var mid:longint;
 83 begin
 84  if (l>=x)and(r<=y) then
 85  begin
 86   t[p].a:=t[p].a+v;
 87   t[p].s:=t[p].s+v*(r-l+1);
 88   exit;
 89  end;
 90  mid:=(l+r)>>1;
 91  t[p<<1].a:=t[p<<1].a+t[p].a;
 92  t[p<<1+1].a:=t[p<<1+1].a+t[p].a;
 93  t[p<<1].s:=t[p<<1].s+(mid-l+1)*t[p].a;
 94  t[p<<1+1].s:=t[p<<1+1].s+(r-mid)*t[p].a;
 95  t[p].a:=0;
 96  if x<=mid then update(l,mid,x,y,v,p<<1);
 97  if y>mid then update(mid+1,r,x,y,v,p<<1+1);
 98  t[p].s:=t[p<<1].s+t[p<<1+1].s;
 99 end;
100 
101 function query(l,r,x,y,p:longint):int64;
102 var mid:longint;
103     tt:int64;
104 begin
105  if (l>=x)and(r<=y) then exit(t[p].s);
106  mid:=(l+r)>>1;
107  t[p<<1].a:=t[p<<1].a+t[p].a;
108  t[p<<1+1].a:=t[p<<1+1].a+t[p].a;
109  t[p<<1].s:=t[p<<1].s+(mid-l+1)*t[p].a;
110  t[p<<1+1].s:=t[p<<1+1].s+(r-mid)*t[p].a;
111  t[p].a:=0;
112  tt:=0;
113  if x<=mid then tt:=tt+query(l,mid,x,y,p<<1);
114  if y>mid then tt:=tt+query(mid+1,r,x,y,p<<1+1);
115  exit(tt);
116 end;
117 
118 function ask(x:longint):int64;
119 var t:int64;
120 begin
121  t:=0;
122  while top[x]<>1 do
123  begin
124   t:=t+query(1,n,tid[top[x]],tid[x],1);
125   x:=fa[top[x]];
126  end;
127  t:=t+query(1,n,1,tid[x],1);
128  exit(t);
129 end;
130 
131 begin
132  assign(input,'bzoj4034.in'); reset(input);
133  assign(output,'bzoj4034.out'); rewrite(output);
134  readln(n,m);
135  for i:=1 to n do read(a[i]);
136  for i:=1 to n-1 do
137  begin
138   readln(x,y);
139   add(x,y);
140   add(y,x);
141  end;
142  dfs1(1);
143  fillchar(flag,sizeof(flag),0);
144  dfs2(1,1);
145  build(1,n,1);
146 
147  for i:=1 to m do
148  begin
149   read(ch);
150   case ch of
151    1:
152    begin
153     read(x,y);
154     update(1,n,tid[x],tid[x],y,1);
155    end;
156    2:
157    begin
158     read(x,y);
159     update(1,n,tid[x],mx[x],y,1);
160    end;
161    3:
162    begin
163     read(x);
164     writeln(ask(x));
165    end;
166   end;
167  end;
168  close(input);
169  close(output);
170 end.

 

 

posted on 2016-11-28 20:14  myx12345  阅读(218)  评论(0编辑  收藏  举报

导航