这是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.
View Code

 

posted on 2015-06-30 18:08  acphile  阅读(221)  评论(0编辑  收藏  举报