BZOJ1095: [ZJOI2007]Hide 捉迷藏(动态点分治)
Description
捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子。某天,Jiajia、Wind和孩子们决定在家里玩
捉迷藏游戏。他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋
子都互相可达。游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯。在起初的
时候,所有的灯都没有被打开。每一次,孩子们只会躲藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要
求打开某个房间的电灯或者关闭某个房间的电灯。为了评估某一次游戏的复杂性,Jiajia希望知道可能的最远的两
个孩子的距离(即最远的两个关灯房间的距离)。 我们将以如下形式定义每一种操作: C(hange) i 改变第i个房
间的照明状态,若原来打开,则关闭;若原来关闭,则打开。 G(ame) 开始一次游戏,查询最远的两个关灯房间的
距离。
Input
第一行包含一个整数N,表示房间的个数,房间将被编号为1,2,3…N的整数。接下来N-1行每行两个整数a, b,
表示房间a与房间b之间有一条走廊相连。接下来一行包含一个整数Q,表示操作次数。接着Q行,每行一个操作,如
上文所示。
Output
对于每一个操作Game,输出一个非负整数到hide.out,表示最远的两个关灯房间的距离。若只有一个房间是关
着灯的,输出0;若所有房间的灯都开着,输出-1。
Sample Input
1 2
2 3
3 4
3 5
3 6
6 7
6 8
7
G
C 1
G
C 2
G
C 1
G
Sample Output
3
3
4
解题思路:
可以将开灯的点都压缩一下,那么这道题就变成了动态求一颗树的直径。
静态的直径可以由一个点子树中不重复的最大值和次大值来更新。
那么可以考虑更新一个点后重新实现Dfs回溯过程,这时候,我们就需要用一个堆来记录这个点的最长链。
那样问题就变成了枚举两个儿子更新答案。
实际上这是不需要的,在每个点再开一个堆记录答案就好了。
最后将每个点的答案记录到的答案推入答案堆中。
这个复杂度还是不能承受。
将树重构形成点分树,每次都在树中暴力更新答案(注意距离要重新到原树中计算)。
代码:(不想写带删除优先队列,就写了个Treap好慢啊QAQ)
1 #include<ctime> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 typedef long long lnt; 6 const int N=100010; 7 struct pnt{ 8 int f; 9 int fa; 10 int hd; 11 int dp; 12 int tp; 13 int dis; 14 int wgt; 15 int val; 16 int mxs; 17 int dcrt; 18 int cnrt; 19 bool vis; 20 }p[N]; 21 struct trnt{ 22 int ls; 23 int rs; 24 int val; 25 int num; 26 int wgt; 27 int rnd; 28 }tr[N*80],strn; 29 struct ent{ 30 int twd; 31 int lst; 32 }e[N<<1]; 33 int n,m; 34 int cnt; 35 int dfn; 36 int siz; 37 int top; 38 int del; 39 int bnum; 40 int root; 41 int size; 42 int maxsize; 43 int ansroot; 44 int sta[N]; 45 int bin[N*80]; 46 char cmd[1000]; 47 void pushup(int rt) 48 { 49 if(!rt) 50 return ; 51 tr[rt].wgt=tr[tr[rt].ls].wgt+tr[tr[rt].rs].wgt+tr[rt].num; 52 return ; 53 } 54 void lturn(int &rt) 55 { 56 int ll=tr[rt].ls; 57 tr[rt].ls=tr[ll].rs; 58 tr[ll].rs=rt; 59 pushup(rt); 60 rt=ll; 61 pushup(rt); 62 return ; 63 } 64 void rturn(int &rt) 65 { 66 int rr=tr[rt].rs; 67 tr[rt].rs=tr[rr].ls; 68 tr[rr].ls=rt; 69 pushup(rt); 70 rt=rr; 71 pushup(rt); 72 return ; 73 } 74 int newp(void) 75 { 76 if(bnum) 77 return bin[bnum--]; 78 return ++siz; 79 } 80 void apply(int &rt) 81 { 82 rt=newp(); 83 tr[rt]=strn; 84 tr[rt].num=1; 85 tr[rt].rnd=rand(); 86 return ; 87 } 88 void Del(int rt) 89 { 90 bin[++bnum]=rt; 91 return ; 92 } 93 void Insert(int &rt,int v) 94 { 95 if(!rt) 96 { 97 apply(rt); 98 tr[rt].val=v; 99 pushup(rt); 100 return ; 101 } 102 if(tr[rt].val==v) 103 tr[rt].num++; 104 else if(tr[rt].val>v) 105 { 106 Insert(tr[rt].ls,v); 107 if(tr[rt].rnd>tr[tr[rt].ls].rnd) 108 lturn(rt); 109 }else{ 110 Insert(tr[rt].rs,v); 111 if(tr[rt].rnd>tr[tr[rt].rs].rnd) 112 rturn(rt); 113 } 114 pushup(rt); 115 return ; 116 } 117 void Delete(int &rt,int v) 118 { 119 if(!rt) 120 return ; 121 if(tr[rt].val==v) 122 { 123 if(tr[rt].num<=1) 124 { 125 if(!tr[rt].ls||!tr[rt].rs) 126 { 127 Del(rt); 128 rt=tr[rt].ls+tr[rt].rs; 129 return ; 130 }else{ 131 if(tr[tr[rt].ls].rnd<tr[tr[rt].rs].rnd) 132 { 133 lturn(rt); 134 Delete(tr[rt].rs,v); 135 }else{ 136 rturn(rt); 137 Delete(tr[rt].ls,v); 138 } 139 } 140 }else 141 tr[rt].num--; 142 }else if(tr[rt].val>v) 143 Delete(tr[rt].ls,v); 144 else 145 Delete(tr[rt].rs,v); 146 pushup(rt); 147 return ; 148 } 149 int kth(int rt,int k) 150 { 151 if(tr[tr[rt].ls].wgt>=k) 152 return kth(tr[rt].ls,k); 153 if(tr[tr[rt].ls].wgt+tr[rt].num>=k) 154 return tr[rt].val; 155 return kth(tr[rt].rs,k-tr[tr[rt].ls].wgt-tr[rt].num); 156 } 157 int Maxval(int rt) 158 { 159 if(tr[rt].wgt==0) 160 return -0x3f3f3f3f; 161 return kth(rt,tr[rt].wgt); 162 } 163 int Secval(int rt) 164 { 165 if(tr[rt].wgt<=1) 166 return -0x3f3f3f3f; 167 return kth(rt,tr[rt].wgt-1); 168 } 169 int Chain(int rt) 170 { 171 if(tr[rt].wgt<2) 172 return 0; 173 return std::max(0,Maxval(rt)+Secval(rt)); 174 } 175 void ade(int f,int t) 176 { 177 cnt++; 178 e[cnt].twd=t; 179 e[cnt].lst=p[f].hd; 180 p[f].hd=cnt; 181 return ; 182 } 183 void Basic_dfs(int x,int f) 184 { 185 p[x].wgt=1; 186 p[x].f=f; 187 p[x].dp=p[f].dp+1; 188 int maxs=-1; 189 for(int i=p[x].hd;i;i=e[i].lst) 190 { 191 int to=e[i].twd; 192 if(to==f) 193 continue; 194 p[to].dis=p[x].dis+1; 195 Basic_dfs(to,x); 196 p[x].wgt+=p[to].wgt; 197 if(maxs<p[to].wgt) 198 { 199 maxs=p[to].wgt; 200 p[x].mxs=to; 201 } 202 } 203 return ; 204 } 205 void Build_dfs(int x,int top) 206 { 207 if(!x) 208 return ; 209 p[x].tp=top; 210 Build_dfs(p[x].mxs,top); 211 for(int i=p[x].hd;i;i=e[i].lst) 212 { 213 int to=e[i].twd; 214 if(to==p[x].f||to==p[x].mxs) 215 continue; 216 Build_dfs(to,to); 217 } 218 return ; 219 } 220 int Lca(int x,int y) 221 { 222 while(p[x].tp!=p[y].tp) 223 { 224 if(p[p[x].tp].dp<p[p[y].tp].dp) 225 std::swap(x,y); 226 x=p[p[x].tp].f; 227 } 228 if(p[x].dp>p[y].dp) 229 std::swap(x,y); 230 return x; 231 } 232 int Dis(int x,int y) 233 { 234 int z=Lca(x,y); 235 return p[x].dis+p[y].dis-2*p[z].dis; 236 } 237 void grc_dfs(int x,int f) 238 { 239 sta[++top]=x; 240 p[x].wgt=1; 241 int maxs=-1; 242 for(int i=p[x].hd;i;i=e[i].lst) 243 { 244 int to=e[i].twd; 245 if(to==f||p[to].vis) 246 continue; 247 grc_dfs(to,x); 248 p[x].wgt+=p[to].wgt; 249 if(maxs<p[to].wgt) 250 maxs=p[to].wgt; 251 } 252 maxs=std::max(maxs,size-p[x].wgt); 253 if(maxs<maxsize) 254 { 255 root=x; 256 maxsize=maxs; 257 } 258 return ; 259 } 260 void bin_dfs(int x,int f) 261 { 262 p[x].fa=f; 263 p[x].vis=true; 264 int tmp=size; 265 if(f) 266 for(int i=1;i<=top;i++) 267 Insert(p[x].cnrt,Dis(f,sta[i])); 268 Insert(p[x].dcrt,0); 269 for(int i=p[x].hd;i;i=e[i].lst) 270 { 271 int to=e[i].twd; 272 if(p[to].vis) 273 continue; 274 root=0; 275 top=0; 276 if(p[to].wgt<p[x].wgt) 277 size=p[to].wgt; 278 else 279 size=tmp-p[x].wgt; 280 maxsize=0x3f3f3f3f; 281 grc_dfs(to,to); 282 int rt=root; 283 bin_dfs(root,x); 284 Insert(p[x].dcrt,Maxval(p[rt].cnrt)); 285 } 286 Insert(ansroot,Chain(p[x].dcrt)); 287 return ; 288 } 289 void Update(int oldans,int newans) 290 { 291 if(oldans==newans) 292 return ; 293 Delete(ansroot,oldans); 294 Insert(ansroot,newans); 295 return ; 296 } 297 void Insert(int x) 298 { 299 int la,na,lc,nc; 300 la=Chain(p[x].dcrt); 301 Insert(p[x].dcrt,0); 302 na=Chain(p[x].dcrt); 303 Update(la,na); 304 for(int i=x;p[i].fa;i=p[i].fa) 305 { 306 lc=Maxval(p[i].cnrt); 307 Insert(p[i].cnrt,Dis(x,p[i].fa)); 308 nc=Maxval(p[i].cnrt); 309 if(lc==nc) 310 continue; 311 la=Chain(p[p[i].fa].dcrt); 312 if(lc!=-0x3f3f3f3f) 313 Delete(p[p[i].fa].dcrt,lc); 314 Insert(p[p[i].fa].dcrt,nc); 315 na=Chain(p[p[i].fa].dcrt); 316 Update(la,na); 317 } 318 return ; 319 } 320 void Delete(int x) 321 { 322 int la,na,lc,nc; 323 la=Chain(p[x].dcrt); 324 Delete(p[x].dcrt,0); 325 na=Chain(p[x].dcrt); 326 Update(la,na); 327 for(int i=x;p[i].fa;i=p[i].fa) 328 { 329 lc=Maxval(p[i].cnrt); 330 Delete(p[i].cnrt,Dis(x,p[i].fa)); 331 nc=Maxval(p[i].cnrt); 332 if(lc==nc) 333 continue; 334 la=Chain(p[p[i].fa].dcrt); 335 Delete(p[p[i].fa].dcrt,lc); 336 if(nc!=-0x3f3f3f3f) 337 Insert(p[p[i].fa].dcrt,nc); 338 na=Chain(p[p[i].fa].dcrt); 339 Update(la,na); 340 } 341 return ; 342 } 343 int main() 344 { 345 scanf("%d",&n); 346 for(int i=1;i<n;i++) 347 { 348 int a,b; 349 scanf("%d%d",&a,&b); 350 ade(a,b); 351 ade(b,a); 352 } 353 Basic_dfs(1,1); 354 Build_dfs(1,1); 355 root=0; 356 size=n; 357 maxsize=0x3f3f3f3f; 358 grc_dfs(1,1); 359 bin_dfs(root,0); 360 scanf("%d",&m); 361 while(m--) 362 { 363 scanf("%s",cmd+1); 364 if(cmd[1]=='G') 365 { 366 if(del==n) 367 puts("-1"); 368 else if(del==n-1) 369 puts("0"); 370 else 371 printf("%d\n",Maxval(ansroot)); 372 }else{ 373 int x; 374 scanf("%d",&x); 375 p[x].val^=1; 376 if(p[x].val) 377 { 378 Delete(x); 379 del++; 380 }else{ 381 Insert(x); 382 del--; 383 } 384 } 385 } 386 return 0; 387 }