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