这是bzoj上AC的第700题,一定要是一道神题!!!
当初分组赛的时候讲过拖到现在才写……
我们考虑把垂直方向移动和水平方向移动分开来考虑,不合法的轮数取二者最小
假设考虑的是垂直方向移动,障碍其实就是类似与x线段一定在y线段之前移动的意思
不难想到拓扑图,如果我们求出了一个向上移动的拓扑图,
不难发现只向一个方向移动一定有解,那么合法的方案就是拓扑排序
而求不合法的操作呢?我们考虑把从前往后删除线段变成从后往前添加线段,
如果添加了一个向上移动的线段i,这个线段x坐标范围内出现一条拓扑排序在i前面的线段,那么不合法
如果添加向下移动的线段i,这是看x坐标范围内是否有拓扑排序在i后面的线段
这我们是可以通过x坐标离散化+线段树维护区间最大值最小值搞定的
那么问题就是我们怎么构造拓扑图
裸的想法是O(n2)的,肯定不行……
不难想到,如果i阻碍j,i阻碍k,j阻碍k,我们没必要连i-->k的边
但具体怎么做呢?对于平面内的线段,在某一个地方做一条垂直x轴的直线
与这条直线相交的线段(由于端点的相交允许,我们考虑左端点与直线相交,不考虑与右端点直线相交),构成的阻碍关系可以简化表示成a1-->a2-->a3-->……
这样我们可以顺着x轴做扫描线,然后按照右端点查询-删除-左端点加入-查询的顺序做
每次查询我们这个线段所连的边,只要是前驱覆盖和后继被覆盖即可,我们可以用平衡树来维护前驱后继
这样就只要构造4*n条边即可,那么问题也解决了
对于水平方向同样的道理,旋转一下坐标轴即可
写了10kb真是爽!!!
1 const inf=100000007; 2 type point=record 3 x,y:longint; 4 end; 5 way=record 6 po,next:longint; 7 end; 8 line=record 9 x,op,id:longint; 10 end; 11 12 var e:array[0..400010] of way; 13 tree,tag:array[0..200010*4,0..1] of longint; 14 lin:array[0..200010] of line; 15 a:array[0..100010,0..1] of point; 16 son:array[0..200010,1..2] of longint; 17 u,du,p,fa,b,loc,h,wh,w,q:array[0..200010] of longint; 18 d:array[0..200010] of longint; 19 sum,x,y,m,root,ans,i,t,n,len:longint; 20 21 function max(a,b:longint):longint; 22 begin 23 if a>b then exit(a) else exit(b); 24 end; 25 26 function min(a,b:longint):longint; 27 begin 28 if a>b then exit(b) else exit(a); 29 end; 30 31 procedure swap(var a,b:point); 32 var c:point; 33 begin 34 c:=a; 35 a:=b; 36 b:=c; 37 end; 38 39 procedure swap(var a,b:longint); 40 var c:longint; 41 begin 42 c:=a; 43 a:=b; 44 b:=c; 45 end; 46 47 function cmp(a,b:line):boolean; 48 begin 49 if a.x=b.x then exit(a.op<b.op) //注意因为是端点触碰允许,所以先做右端点的扫描线 50 else exit(a.x<b.x); 51 end; 52 53 procedure add(x,y:longint); 54 begin 55 inc(len); 56 e[len].po:=y; 57 e[len].next:=p[x]; 58 p[x]:=len; 59 inc(du[y]); 60 end; 61 62 procedure sortu(l,r:longint); 63 var i,j,x:longint; 64 begin 65 i:=l; 66 j:=r; 67 x:=d[(l+r) shr 1]; 68 repeat 69 while d[i]<x do inc(i); 70 while x<d[j] do dec(j); 71 if not(i>j) then 72 begin 73 swap(d[i],d[j]); 74 inc(i); 75 dec(j); 76 end; 77 until i>j; 78 if l<j then sortu(l,j); 79 if i<r then sortu(i,r); 80 end; 81 82 procedure sortl(l,r:longint); 83 var i,j:longint; 84 x,y:line; 85 begin 86 i:=l; 87 j:=r; 88 x:=lin[(l+r) shr 1]; 89 repeat 90 while cmp(lin[i],x) do inc(i); 91 while cmp(x,lin[j]) do dec(j); 92 if not(i>j) then 93 begin 94 y:=lin[i]; lin[i]:=lin[j]; lin[j]:=y; 95 inc(i); 96 dec(j); 97 end; 98 until i>j; 99 if l<j then sortl(l,j); 100 if i<r then sortl(i,r); 101 end; 102 103 procedure topsort; 104 var h,r,i,x,y:longint; 105 begin 106 h:=1; 107 r:=0; 108 for i:=1 to n do 109 if du[i]=0 then 110 begin 111 inc(r); 112 q[r]:=i; 113 end; 114 115 while h<=r do 116 begin 117 x:=q[h]; 118 i:=p[x]; 119 while i<>0 do 120 begin 121 y:=e[i].po; 122 dec(du[y]); 123 if du[y]=0 then 124 begin 125 inc(r); 126 q[r]:=y; 127 end; 128 i:=e[i].next; 129 end; 130 inc(h); 131 end; 132 end; 133 134 procedure cov(i,z:longint); 135 begin 136 tree[i,0]:=min(tree[i,0],z); 137 tree[i,1]:=max(tree[i,1],z); 138 tag[i,0]:=min(tag[i,0],z); 139 tag[i,1]:=max(tag[i,1],z); 140 end; 141 142 procedure push(i:longint); 143 begin 144 if tag[i,0]<inf then 145 begin 146 cov(i*2,tag[i,0]); 147 cov(i*2+1,tag[i,0]); 148 tag[i,0]:=inf; 149 end; 150 if tag[i,1]>0 then 151 begin 152 cov(i*2,tag[i,1]); 153 cov(i*2+1,tag[i,1]); 154 tag[i,1]:=0; 155 end; 156 end; 157 158 procedure build(i,l,r:longint); 159 var m:longint; 160 begin 161 tree[i,0]:=inf; 162 tag[i,0]:=inf; 163 tree[i,1]:=0; 164 tag[i,1]:=0; 165 if l<>r then 166 begin 167 m:=(l+r) shr 1; 168 build(i*2,l,m); 169 build(i*2+1,m+1,r); 170 end; 171 end; 172 173 procedure ins(i,l,r,z:longint); 174 var m:longint; 175 begin 176 if (x<=l) and (y>=r) then cov(i,z) 177 else begin 178 m:=(l+r) shr 1; 179 push(i); 180 if x<=m then ins(i*2,l,m,z); 181 if y>m then ins(i*2+1,m+1,r,z); 182 tree[i,0]:=min(tree[i*2,0],tree[i*2+1,0]); 183 tree[i,1]:=max(tree[i*2,1],tree[i*2+1,1]); 184 end; 185 end; 186 187 function find(l,r,x:longint):longint; 188 var m:longint; 189 begin 190 while l<=r do 191 begin 192 m:=(l+r) shr 1; 193 if d[m]=x then exit(m); 194 if d[m]>x then r:=m-1 else l:=m+1; 195 end; 196 end; 197 198 function ask(i,l,r,k:longint):longint; 199 var m,s:longint; 200 begin 201 if (x<=l) and (y>=r) then exit(tree[i,k]) 202 else begin 203 m:=(l+r) shr 1; 204 push(i); 205 if k=0 then 206 begin 207 s:=inf; 208 if x<=m then s:=min(s,ask(i*2,l,m,k)); 209 if y>m then s:=min(s,ask(i*2+1,m+1,r,k)); 210 end 211 else begin 212 s:=0; 213 if x<=m then s:=max(s,ask(i*2,l,m,k)); 214 if y>m then s:=max(s,ask(i*2+1,m+1,r,k)); 215 end; 216 exit(s); 217 end; 218 end; 219 220 function make(x,y,z:longint):line; 221 begin 222 make.x:=x; 223 make.id:=y; 224 make.op:=z; 225 end; 226 227 procedure unique; 228 var i,t:longint; 229 begin 230 t:=0; 231 for i:=1 to n do 232 begin 233 inc(t); d[t]:=a[i,0].x; 234 inc(t); d[t]:=a[i,1].x; 235 end; 236 sortu(1,t); 237 m:=1; 238 for i:=2 to t do 239 if d[i]<>d[m] then 240 begin 241 inc(m); 242 d[m]:=d[i]; 243 end; 244 end; 245 246 function cmp(i,j:longint):boolean; //判断阻碍关系 247 var mid,pa,pb:extended; 248 begin 249 mid:=(max(a[i,0].x,a[j,0].x)+min(a[i,1].x,a[j,1].x))/2; 250 pa:=(mid-a[i,0].x)/(a[i,1].x-a[i,0].x)*(a[i,1].y-a[i,0].y)+a[i,0].y; 251 pb:=(mid-a[j,0].x)/(a[j,1].x-a[j,0].x)*(a[j,1].y-a[j,0].y)+a[j,0].y; 252 exit(pa<pb); 253 end; 254 255 procedure rotate(x,w:longint); 256 var y:longint; 257 begin 258 y:=fa[x]; 259 if fa[y]<>0 then 260 begin 261 if son[fa[y],1]=y then son[fa[y],1]:=x 262 else son[fa[y],2]:=x; 263 end 264 else root:=x; 265 fa[x]:=fa[y]; 266 son[y,3-w]:=son[x,w]; 267 if son[x,w]<>0 then fa[son[x,w]]:=y; 268 son[x,w]:=y; 269 fa[y]:=x; 270 end; 271 272 procedure up(x:longint); 273 var y:longint; 274 begin 275 y:=fa[x]; 276 while y>0 do 277 begin 278 if h[y]>h[x] then 279 begin 280 if son[y,1]=x then rotate(x,2) 281 else rotate(x,1); 282 y:=fa[x]; 283 end 284 else break; 285 end; 286 end; 287 288 procedure sift(i:longint); 289 var j1,j2:longint; 290 begin 291 repeat 292 j1:=son[i,1]; j2:=son[i,2]; 293 if (j1=0) and (j2=0) then exit; 294 if (j1=0) or ((h[j1]>h[j2]) and (j2<>0)) then rotate(j2,1) 295 else if (j2=0) or ((j1<>0) and (h[j1]<h[j2])) then rotate(j1,2); 296 until false; 297 end; 298 299 procedure newnode(x:longint); 300 var p:longint; 301 begin 302 inc(t); inc(sum); 303 b[t]:=x; loc[x]:=t; 304 h[t]:=trunc(random*inf)+1; 305 fa[t]:=0; son[t,1]:=0; son[t,2]:=0; 306 if root=0 then 307 begin 308 root:=t; 309 exit; 310 end 311 else begin 312 p:=root; 313 repeat 314 if cmp(x,b[p]) then 315 begin 316 if son[p,1]=0 then 317 begin 318 son[p,1]:=t; 319 break; 320 end; 321 p:=son[p,1]; 322 end 323 else begin 324 if son[p,2]=0 then 325 begin 326 son[p,2]:=t; 327 break; 328 end; 329 p:=son[p,2]; 330 end; 331 until false; 332 fa[t]:=p; 333 up(t); 334 end; 335 end; 336 337 procedure delete(x:longint); 338 begin 339 sift(x); 340 if fa[x]<>0 then 341 begin 342 if son[fa[x],1]=x then son[fa[x],1]:=0 343 else son[fa[x],2]:=0; 344 end; 345 fa[x]:=0; 346 dec(sum); 347 if sum=0 then root:=0; 348 end; 349 350 function pre(p,x:longint):longint; 351 var tm:longint; 352 begin 353 if p=0 then exit(-1) 354 else begin 355 if cmp(b[p],x) then 356 begin 357 tm:=pre(son[p,2],x); 358 if tm=-1 then exit(b[p]) 359 else exit(tm); 360 end 361 else exit(pre(son[p,1],x)); 362 end; 363 end; 364 365 function suffix(p,x:longint):longint; 366 var tm:longint; 367 begin 368 if p=0 then exit(-1) 369 else begin 370 if cmp(x,b[p]) then 371 begin 372 tm:=suffix(son[p,1],x); 373 if tm=-1 then exit(b[p]) 374 else exit(tm); 375 end 376 else exit(suffix(son[p,2],x)); 377 end; 378 end; 379 380 procedure work(p1,p2:longint); 381 var i,r,z,pr,su,no:longint; 382 begin 383 len:=0; 384 fillchar(p,sizeof(p),0); 385 fillchar(du,sizeof(du),0); 386 r:=0; 387 for i:=1 to n do 388 begin 389 inc(r); lin[r]:=make(a[i,0].x,i,1); 390 inc(r); lin[r]:=make(a[i,1].x,i,0); 391 end; 392 sortl(1,r); 393 i:=1; t:=0; root:=0; 394 while i<=r do 395 begin 396 z:=lin[i].x; 397 while (i<=r) and (lin[i].x=z) do 398 begin 399 if lin[i].op=1 then newnode(lin[i].id); 400 no:=lin[i].id; 401 pr:=pre(root,no); 402 su:=suffix(root,no); 403 if (pr<>-1) and (pr<>no) then add(no,pr); 404 if (su<>-1) and (su<>no) then add(su,no); 405 if lin[i].op=0 then delete(loc[no]); 406 inc(i); 407 end; 408 end; 409 topsort; 410 for i:=1 to n do 411 w[q[i]]:=i; 412 unique; 413 build(1,1,m); 414 for i:=n downto 1 do 415 begin 416 x:=find(1,m,a[wh[i],0].x); 417 y:=find(1,m,a[wh[i],1].x); 418 dec(y); 419 if (u[i]=p1) or (u[i]=p2) then 420 begin 421 if (u[i]=1) or (u[i]=2) then no:=0 else no:=1; 422 z:=ask(1,1,m,no); 423 if (no=1) and (z>w[wh[i]]) or (no=0) and (z<w[wh[i]]) then 424 ans:=min(ans,i); 425 end; 426 ins(1,1,m,w[wh[i]]); 427 end; 428 end; 429 430 begin 431 randomize; 432 readln(n); 433 for i:=1 to n do 434 begin 435 read(a[i,0].x,a[i,0].y); 436 read(a[i,1].x,a[i,1].y); 437 if a[i,0].x>a[i,1].x then swap(a[i,0],a[i,1]); 438 end; 439 for i:=1 to n do 440 readln(wh[i],u[i]); 441 ans:=n; 442 work(1,3); 443 for i:=1 to n do 444 begin 445 swap(a[i,0].x,a[i,0].y); 446 swap(a[i,1].x,a[i,1].y); 447 if a[i,0].x>a[i,1].x then swap(a[i,0],a[i,1]); 448 end; 449 work(0,2); 450 writeln(ans); 451 for i:=1 to n do 452 writeln(q[i],' 2'); 453 end.