【BZOJ3991】寻宝游戏(虚树,DFS序,splay)

题意:求在树中从任意点开始,经过若干个关键点回到原点的最小距离

要求支持在线将某个点设置(取消)为关键点,以及询问答案

n,m<=100000 len[i]<=10^9

思路:显然是一个虚树的模型,但并不需要虚树

其实就是求虚树的所有路径长度之和的2倍

思考后可以发现,必定是按DFS序从小到大走,再从最大点回到最小点总路程最短

所以只需要维护DFS序的插入,删除,前驱,后继,最大,最小,splay即可

插入点i时找到与它DFS序相邻的点x和y,对答案有dis(x,i)+dis(y,i)-dis(x,y)的贡献

最后加上首尾长度

  1 var t:array[0..500000,0..1]of longint;
  2     f:array[1..110000,0..17]of longint;
  3     fa,rev,size:array[0..500000]of longint;
  4     flag,dfn,id,dep,head,vet,next,len,b:array[1..500000]of longint;
  5     dis,num:array[0..500000]of int64;
  6     n,m,i,x,y,tot,root,cnt,time,z:longint;
  7     ans,v,tmp,oo,l,r:int64;
  8 
  9 procedure swap(var x,y:longint);
 10 var t:longint;
 11 begin
 12  t:=x; x:=y; y:=t;
 13 end;
 14 
 15 procedure pushup(x:longint);
 16 var l,r:longint;
 17 begin
 18  l:=t[x,0]; r:=t[x,1];
 19  size[x]:=size[l]+size[r]+1;
 20 end;
 21 
 22 procedure rotate(x:longint;var k:longint);
 23 var y,z,l,r:longint;
 24 begin
 25  y:=fa[x]; z:=fa[y];
 26  if t[y,0]=x then l:=0
 27   else l:=1;
 28  r:=l xor 1;
 29  if y<>k then
 30  begin
 31   if t[z,0]=y then t[z,0]:=x
 32    else t[z,1]:=x;
 33  end
 34   else k:=x;
 35  fa[x]:=z; fa[y]:=x; fa[t[x,r]]:=y;
 36  t[y,l]:=t[x,r]; t[x,r]:=y;
 37  pushup(y);
 38  pushup(x);
 39 end;
 40 
 41 procedure splay(x:longint;var k:longint);
 42 var y,z:longint;
 43 begin
 44  while x<>k do
 45  begin
 46   y:=fa[x]; z:=fa[y];
 47   if y<>k then
 48   begin
 49    if (t[y,0]=x)xor(t[z,0]=y) then rotate(x,k)
 50     else rotate(y,k);
 51   end
 52    else k:=x;
 53   rotate(x,k);
 54  end;
 55 end;
 56 
 57 function kth(x:longint):longint;
 58 var k,tmp:longint;
 59 begin
 60  k:=root;
 61  while k<>0 do
 62  begin
 63   tmp:=size[t[k,0]]+1;
 64   if tmp=x then exit(k)
 65    else if tmp>x then k:=t[k,0]
 66     else
 67     begin
 68      k:=t[k,1]; x:=x-tmp;
 69     end;
 70  end;
 71 end;
 72 
 73 function pred(x:int64):int64;
 74 var k:longint;
 75     last:int64;
 76 begin
 77  k:=root; last:=-oo;
 78  while k<>0 do
 79  begin
 80   if num[k]<x then begin last:=num[k]; k:=t[k,1]; end
 81    else k:=t[k,0];
 82  end;
 83  exit(last);
 84 end;
 85 
 86 function succ(x:int64):int64;
 87 var k:longint;
 88     last:int64;
 89 begin
 90  k:=root; last:=oo;
 91  while k<>0 do
 92  begin
 93   if num[k]>x then begin last:=num[k]; k:=t[k,0]; end
 94    else k:=t[k,1];
 95  end;
 96  exit(last);
 97 end;
 98 
 99 function rank(x:int64):longint;
100 var k:longint;
101 begin
102  rank:=1; k:=root;
103  while k<>0 do
104  begin
105   if num[k]<x then begin rank:=rank+size[t[k,0]]+1; k:=t[k,1]; end
106    else k:=t[k,0];
107  end;
108 end;
109 
110 procedure ins(x:int64);
111 var k,k1,k2:longint;
112 begin
113  k:=rank(x);
114  k1:=kth(k-1);
115  k2:=kth(k);
116  splay(k1,root);
117  splay(k2,t[root,1]);
118  k:=t[root,1];
119  inc(cnt); t[k,0]:=cnt; fa[cnt]:=k; size[cnt]:=1; num[cnt]:=x;
120  inc(tot);
121 end;
122 
123 procedure del(x:int64);
124 var k,k1,k2:longint;
125 begin
126  k:=rank(x);
127  k1:=kth(k-1);
128  k2:=kth(k+1);
129  splay(k1,root);
130  splay(k2,t[root,1]);
131  k1:=t[root,1]; k2:=t[k1,0];
132  t[k1,0]:=0; size[k1]:=size[t[k1,1]]+1;
133  fa[k2]:=0; t[k2,0]:=0; t[k2,1]:=0; size[k2]:=0; num[k2]:=0;
134  dec(tot);
135 end;
136 
137 function lca(x,y:longint):longint;
138 var i,d:longint;
139 begin
140  if dep[x]<dep[y] then swap(x,y);
141  d:=dep[x]-dep[y];
142  for i:=0 to 17 do
143   if d and (1<<i)>0 then x:=f[x,i];
144  for i:=17 downto 0 do
145   if f[x,i]<>f[y,i] then
146   begin
147    x:=f[x,i]; y:=f[y,i];
148   end;
149  if x=y then exit(x);
150  exit(f[x,0]);
151 end;
152 
153 function query(x,y:longint):int64;
154 var q:longint;
155 begin
156  q:=lca(x,y);
157  exit(dis[x]+dis[y]-2*dis[q]);
158 end;
159 
160 procedure add(a,b,c:longint);
161 begin
162  inc(tot);
163  next[tot]:=head[a];
164  vet[tot]:=b;
165  len[tot]:=c;
166  head[a]:=tot;
167 end;
168 
169 procedure dfs(u:longint);
170 var i,e,v:longint;
171 begin
172  flag[u]:=1;
173  inc(time); dfn[u]:=time; id[time]:=u;
174  for i:=1 to 17 do
175  begin
176   if dep[u]<1<<i then break;
177   f[u,i]:=f[f[u,i-1],i-1];
178  end;
179  e:=head[u];
180  while e<>0 do
181  begin
182   v:=vet[e];
183   if flag[v]=0 then
184   begin
185    dep[v]:=dep[u]+1;
186    dis[v]:=dis[u]+len[e];
187    f[v,0]:=u;
188    dfs(v);
189   end;
190   e:=next[e];
191  end;
192 end;
193 
194 begin
195  assign(input,'bzoj3991.in'); reset(input);
196  assign(output,'bzoj3991.out'); rewrite(output);
197  readln(n,m);
198  for i:=1 to n-1 do
199  begin
200   readln(x,y,z);
201   add(x,y,z);
202   add(y,x,z);
203  end;
204  dfs(1);
205  oo:=1<<60;
206  num[1]:=oo; t[1,0]:=2; size[1]:=2;
207  num[2]:=-oo; fa[2]:=1; size[2]:=1;
208  root:=1; cnt:=2; tot:=2;
209  for i:=1 to m do
210  begin
211   readln(x);
212   if b[x]=0 then begin v:=1; ins(dfn[x]); end
213    else begin v:=-1; del(dfn[x]); end;
214   b[x]:=b[x] xor 1;
215   l:=pred(dfn[x]);
216   r:=succ(dfn[x]);
217   if l<>-oo then ans:=ans+v*query(id[l],x);
218   if r<>oo then ans:=ans+v*query(id[r],x);
219   if (l<>-oo)and(r<>oo) then ans:=ans-v*query(id[l],id[r]);
220   tmp:=0;
221   if tot>3 then
222   begin
223    l:=kth(2);
224    r:=kth(tot-1);
225    tmp:=query(id[num[l]],id[num[r]]);
226   end;
227   writeln(ans+tmp);
228  end;
229  close(input);
230  close(output);
231 end.

 

posted on 2017-02-13 16:35  myx12345  阅读(324)  评论(0编辑  收藏  举报

导航