【BZOJ3626】LCA(树上差分,树链剖分)

题意:给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。
设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。
有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[LCA(i,z)]。
(即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)

n<=50000

思路:From THU爷 LYY

我们考虑这样一种暴力:

对于dep[lca(i,j)],可以将0~i路径上的点的权值+1,那么答案就是0~j路径上的点的权值之和。

因此对于[l,r]区间,可以将每个点到根节点的权值+1,那么答案ans[l,r]就是0~z路径上的点的权值之和。

显然ans[l,r]=ans[1,r]-ans[1,l-1]。

那么可以树链剖分,然后将0~n-1这n个点插入线段树中,顺便求出答案,复杂度O(nlogn^2)。

  1 const mo=201314;
  2 var t:array[0..500000]of record
  3                           a,s,l:longint;
  4                          end;
  5     head,vet,next,head1,vet1,next1,c,d,
  6     size,son,tid,id,top,flag,dep,fa,ans:array[0..150000]of longint;
  7     n,q,i,j,l,r,z,tot,f,v,time,e:longint;
  8 
  9 
 10 procedure add(a,b:longint);
 11 begin
 12  inc(tot);
 13  next[tot]:=head[a];
 14  vet[tot]:=b;
 15  head[a]:=tot;
 16 end;
 17 
 18 procedure swap(var x,y:longint);
 19 var t:longint;
 20 begin
 21  t:=x; x:=y; y:=t;
 22 end;
 23 
 24 procedure addq(a,b,c1,d1:longint);
 25 begin
 26  inc(tot);
 27  next1[tot]:=head1[a];
 28  vet1[tot]:=b;
 29  c[tot]:=c1;
 30  d[tot]:=d1;
 31  head1[a]:=tot;
 32 end;
 33 
 34 procedure dfs1(u:longint);
 35 var e,v,maxsize,t:longint;
 36 begin
 37  flag[u]:=1; size[u]:=1; son[u]:=0; t:=0;
 38  e:=head[u];
 39  while e<>0 do
 40  begin
 41   v:=vet[e];
 42   if flag[v]=0 then
 43   begin
 44    dep[v]:=dep[u]+1;
 45    dfs1(v);
 46    size[u]:=size[u]+size[v];
 47    if size[v]>t then
 48    begin
 49     t:=size[v]; son[u]:=v;
 50    end;
 51    e:=next[e];
 52   end;
 53  end;
 54 end;
 55 
 56 procedure dfs2(u,ance:longint);
 57 var e,v:longint;
 58 begin
 59  flag[u]:=1; inc(time); tid[u]:=time; id[time]:=u; top[u]:=ance;
 60  if son[u]>0 then dfs2(son[u],ance);
 61  e:=head[u];
 62  while e<>0 do
 63  begin
 64   v:=vet[e];
 65   if flag[v]=0 then dfs2(v,v);
 66   e:=next[e];
 67  end;
 68 end;
 69 
 70 procedure hash(var x:longint);
 71 begin
 72  if x>=mo then x:=x mod mo;
 73 end;
 74 procedure pushdown(x:longint);
 75 var l,r,tmp:longint;
 76 begin
 77  tmp:=t[x].a;
 78  if tmp=0 then exit;
 79  l:=x<<1; r:=l+1;
 80  t[l].a:=t[l].a+tmp; hash(t[l].a);
 81  t[r].a:=t[r].a+tmp; hash(t[r].a);
 82  t[l].s:=t[l].s+t[l].l*tmp; hash(t[l].s);
 83  t[r].s:=t[r].s+t[r].l*tmp; hash(t[r].s);
 84  t[x].a:=0;
 85 end;
 86 
 87 procedure pushup(x:longint);
 88 var l,r:longint;
 89 begin
 90  l:=x<<1; r:=l+1;
 91  t[x].s:=t[l].s+t[r].s; hash(t[x].s);
 92 end;
 93 
 94 procedure build(l,r,p:longint);
 95 var mid:longint;
 96 begin
 97  t[p].l:=r-l+1;
 98  if l=r then exit;
 99  mid:=(l+r)>>1;
100  build(l,mid,p<<1);
101  build(mid+1,r,p<<1+1);
102 end;
103 
104 function query(l,r,x,y,p:longint):longint;
105 var mid:longint;
106 begin
107  if (l>=x)and(r<=y) then exit(t[p].s);
108  mid:=(l+r)>>1;
109  pushdown(p);
110  query:=0;
111  if x<=mid then query:=query+query(l,mid,x,y,p<<1);
112  if y>mid then query:=query+query(mid+1,r,x,y,p<<1+1);
113 // if query>=mo then query:=query-mo;
114  hash(query);
115 end;
116 
117 procedure update(l,r,x,y,p:longint);
118 var mid:longint;
119 begin
120  if (l>=x)and(r<=y) then
121  begin
122   inc(t[p].a);
123  // if t[p].a>=mo then t[p].a:=t[p].a-mo;
124   hash(t[p].a);
125   t[p].s:=t[p].s+t[p].l;
126   hash(t[p].s);
127  // if t[p].s>=mo then t[p].s:=t[p].s-mo;
128   exit;
129  end;
130  mid:=(l+r)>>1;
131  pushdown(p);
132  if x<=mid then update(l,mid,x,y,p<<1);
133  if y>mid then update(mid+1,r,x,y,p<<1+1);
134  pushup(p);
135 end;
136 
137 procedure change(k:longint);
138 begin
139  while top[k]<>1 do
140  begin
141   update(1,n,tid[top[k]],tid[k],1);
142   k:=fa[top[k]];
143  end;
144  update(1,n,1,tid[k],1);
145 end;
146 
147 function clac(k:longint):longint;
148 begin
149  clac:=0;
150  while top[k]<>1 do
151  begin
152   clac:=clac+query(1,n,tid[top[k]],tid[k],1);
153 //  if clac>=mo then clac:=clac-mo;
154   hash(clac);
155   k:=fa[top[k]];
156  end;
157  clac:=clac+query(1,n,1,tid[k],1);
158 // if clac>=mo then clac:=clac-mo;
159  hash(clac);
160 end;
161 
162 begin
163  assign(input,'bzoj3626.in'); reset(input);
164  assign(output,'bzoj3626.out'); rewrite(output);
165  readln(n,q);
166  for i:=2 to n do
167  begin
168   read(fa[i]); inc(fa[i]);
169   add(fa[i],i);
170  end;
171  dfs1(1);
172  fillchar(flag,sizeof(flag),0);
173  dfs2(1,1);
174  tot:=0;
175  for i:=1 to q do
176  begin
177   readln(l,r,z);
178   inc(l); inc(r); inc(z);
179   addq(l-1,i,z,-1);
180   addq(r,i,z,1);
181  end;
182  build(1,n,1);
183  for i:=1 to n do
184  begin
185   change(i);
186   e:=head1[i];
187   while e<>0 do
188   begin
189    v:=vet1[e]; j:=c[e]; f:=d[e];
190    ans[v]:=(ans[v]+f*clac(j) mod mo+mo) mod mo;
191    e:=next1[e];
192   end;
193  end;
194  for i:=1 to q do writeln(ans[i]);
195 
196  close(input);
197  close(output);
198 end.

 

posted on 2017-02-21 19:31  myx12345  阅读(236)  评论(0编辑  收藏  举报

导航