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