• bzoj2584


    这是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
  • 相关阅读:
    python爬虫实例--爬取拉勾网
    面试时,如何回答你还有什么想要了解的?
    深入理解三次握手四次挥手以及使用scapy实现ddos雏形
    解决socket粘包的两种low版模式 os.popen()和struct模块
    浅谈osi模型 三次握手 四次挥手 ddos攻击原理
    渲染相关书籍
    unity 场景编辑器物体加图标
    音乐模拟器
    3d服装制作软件
    uv投影插值
  • 原文地址:https://www.cnblogs.com/phile/p/4611273.html
Copyright © 2020-2023  润新知