[BZOJ3991][SDOI2015]寻宝游戏
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ3991][SDOI2015]寻宝游戏相关的知识,希望对你有一定的参考价值。
睡前写题解。此题Pascal党有难度max的buff……毕竟C++有set这种黑科技,P党只好手写平衡树。然而这还不是最主要的,最大的代码难点在于此题有奇怪的边界处理,加了一堆特判,用封好的set大概会清晰很多。
脑补一下就会发现答案就是所有被选中的点所构成的虚树的边权和的两倍,走路的过程就是在虚树上dfs的过程。这样我们可以把原树先dfs一遍,在虚树中dfs的时候访问关键点的先后顺序与原树中dfs是一致的,这样我们对于一些关键点可以把它们按照dfs序从前往后排,由第一个点开始走,一个一个往后依次走,答案就是这个序列中所有相邻两点在树上的距离之和,别忘了从最后一个点还要走回第一个点(可以把这个序列想象成环形的),这个序列用平衡树维护就好了,需要注意的是在加入/删除点的时候点如果没有后继那么后继算第一个点,如果没有前件那么前件算最后一个点。两点间的距离lca搞一搞。个人觉得代码实现才是难度最大的,代码写得丑QAQ
1 program bzoj3991; 2 const maxn=100010; 3 var dfn,last,fa:array[0..maxn] of longint; 4 dep:array[0..maxn] of int64; 5 dfsseq:array[0..2*maxn] of longint; 6 st:array[0..2*maxn,0..20] of longint; //according to dep 7 trea:array[0..maxn] of boolean; 8 ed:array[0..maxn*2] of record o,next,l:longint; end; 9 tree:array[0..maxn] of record fa,key,w:longint; son:array[0..1] of longint;end; 10 //according to dfn 11 log:array[0..2*maxn] of longint; 12 ans:int64; 13 n,m,i,tot,t1,t2,t,u,v,w:longint; 14 procedure rotate(x,dir:longint); 15 var f,s:longint; 16 begin 17 f:=tree[x].fa; 18 s:=tree[x].son[dir]; 19 tree[x].son[dir]:=tree[s].son[1-dir]; 20 tree[tree[s].son[1-dir]].fa:=x; 21 tree[s].son[1-dir]:=x; 22 tree[x].fa:=s; 23 tree[s].fa:=f; 24 if tree[f].son[0]=x then tree[f].son[0]:=s 25 else tree[f].son[1]:=s; 26 end; 27 function min(x,y:longint):longint; 28 begin 29 if dep[x]<dep[y] then exit(x) else exit(y); 30 end; 31 procedure add(u,v,w:longint); 32 begin 33 inc(tot); 34 ed[tot].next:=last[u]; 35 last[u]:=tot; 36 ed[tot].o:=v; 37 ed[tot].l:=w; 38 end; 39 procedure dfs(x:Longint;d:int64); 40 var i:longint; 41 begin 42 inc(tot); 43 dfn[x]:=tot; 44 dep[x]:=d; 45 dfsseq[tot]:=x; 46 i:=last[x]; 47 while i<>0 do 48 begin 49 if fa[x]<>ed[i].o then 50 begin 51 fa[ed[i].o]:=x; 52 dfs(ed[i].o,d+ed[i].l); 53 inc(tot); 54 dfsseq[tot]:=x; 55 end; 56 i:=ed[i].next; 57 end; 58 end; 59 function suc(x,p:longint):longint; 60 var t:longint; 61 begin 62 if x=0 then exit(0); 63 if dfn[tree[x].key]<=dfn[p] then exit(suc(tree[x].son[1],p)) 64 else begin t:=suc(tree[x].son[0],p); if t=0 then exit(x) else exit(t); end; 65 end; 66 function pre(x,p:longint):longint; 67 var t:longint; 68 begin 69 if x=0 then exit(0); 70 if dfn[tree[x].key]>=dfn[p] then exit(pre(tree[x].son[0],p)) 71 else begin t:=pre(tree[x].son[1],p); if t=0 then exit(x) else exit(t); end; 72 end; 73 function findmin:longint; 74 var i:longint; 75 begin 76 i:=tree[1].son[1]; 77 while tree[i].son[0]<>0 do i:=tree[i].son[0]; 78 exit(i); 79 end; 80 function findmax:longint; 81 var i:longint; 82 begin 83 i:=1; 84 while tree[i].son[1]<>0 do i:=tree[i].son[1]; 85 exit(i); 86 end; 87 procedure join(x:longint); 88 var i:Longint; 89 begin 90 i:=1; 91 while tree[i].son[ord(dfn[tree[x].key]>dfn[tree[i].key])]<>0 do 92 i:=tree[i].son[ord(dfn[tree[x].key]>dfn[tree[i].key])]; 93 tree[i].son[ord(dfn[tree[x].key]>dfn[tree[i].key])]:=x; 94 tree[x].fa:=i; 95 tree[x].w:=random(100000000); 96 while tree[x].w<tree[tree[x].fa].w do 97 if tree[tree[x].fa].son[1]=x then rotate(tree[x].fa,1) 98 else rotate(tree[x].fa,0); 99 end; 100 function find(x:longint):longint; 101 var i:longint; 102 begin 103 i:=1; 104 while tree[i].key<>x do 105 i:=tree[i].son[ord(dfn[x]>dfn[tree[i].key])]; 106 exit(i); 107 end; 108 procedure del(x:longint); 109 begin 110 while (tree[x].son[0]<>0)or(tree[x].son[1]<>0) do 111 if tree[tree[x].son[0]].w<tree[tree[x].son[1]].w then rotate(x,0) 112 else rotate(x,1); 113 if tree[tree[x].fa].son[0]=x then tree[tree[x].fa].son[0]:=0 114 else tree[tree[x].fa].son[1]:=0; 115 tree[x].fa:=0; 116 end; 117 procedure STprework; 118 var i,j:longint; 119 begin 120 log[1]:=0; 121 for i:=2 to tot do 122 if i and (i-1)=0 then log[i]:=log[i-1]+1 123 else log[i]:=log[i-1]; 124 for i:=1 to tot do 125 st[i,0]:=dfsseq[i]; 126 for i:=1 to log[tot] do 127 for j:=1 to tot do 128 if j+1 shl (i-1)<=tot then st[j,i]:=min(st[j,i-1],st[j+1 shl (i-1),i-1]) 129 else st[j,i]:=st[j,i-1]; 130 end; 131 function dis(x,y:longint):int64; 132 var lca:longint; 133 begin 134 if dfn[x]>dfn[y] then 135 begin 136 lca:=x; 137 x:=y; 138 y:=lca; 139 end; 140 lca:=min(st[dfn[x],log[dfn[y]-dfn[x]+1]],st[dfn[y]-1 shl log[dfn[y]-dfn[x]+1]+1,log[dfn[y]-dfn[x]+1]]); 141 exit(dep[x]+dep[y]-2*dep[lca]); 142 end; 143 begin 144 randomize; 145 fillchar(last,sizeof(last),0); 146 readln(n,m); 147 tot:=0; 148 for i:=1 to n-1 do 149 begin 150 readln(u,v,w); 151 add(u,v,w); 152 add(v,u,w); 153 end; 154 tot:=0; 155 dfs(1,0); 156 STprework; 157 tree[1].key:=0; 158 tree[1].w:=-maxlongint; 159 tree[0].w:=maxlongint; 160 dfn[0]:=0; 161 tot:=1; 162 ans:=0; 163 fillchar(trea,sizeof(trea),0); 164 for i:=1 to m do 165 begin 166 readln(t); 167 if trea[t] then 168 begin 169 trea[t]:=false; 170 t1:=pre(tree[1].son[1],t); 171 t2:=suc(tree[1].son[1],t); 172 if t1=0 then t1:=findmax; 173 if t2=0 then t2:=findmin; 174 if (t1<>0)and(t2<>0) then 175 ans:=ans-dis(t,tree[t1].key)-dis(t,tree[t2].key)+dis(tree[t1].key,tree[t2].key); 176 del(find(t)); 177 writeln(ans); 178 end 179 else 180 begin 181 trea[t]:=true; 182 inc(tot); 183 tree[tot].key:=t; 184 join(tot); 185 t1:=pre(tree[1].son[1],t); 186 t2:=suc(tree[1].son[1],t); 187 if t1=0 then t1:=findmax; 188 if t2=0 then t2:=findmin; 189 if (t1<>0)and(t2<>0) then 190 ans:=ans+dis(t,tree[t1].key)+dis(t,tree[t2].key)-dis(tree[t1].key,tree[t2].key); 191 writeln(ans); 192 end; 193 end; 194 end.
以上是关于[BZOJ3991][SDOI2015]寻宝游戏的主要内容,如果未能解决你的问题,请参考以下文章