[BZOJ3991][SDOI2015]寻宝游戏

     睡前写题解。此题Pascal党有难度maxbuff……毕竟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.

 

posted @ 2016-06-15 23:20 lkmcfj 阅读(...) 评论(...) 编辑 收藏