您的位置:首页 > 其它

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

2017-02-21 19:31 555 查看

题意:给出一个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

.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.

[p] 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: