• POJ3667 Hotel


    题目大意:

      有一段长为n的线段,在这条线段上进行操作:

      1.找出最靠前的长度为l的空线段,并把一个长为l的线段插入在这个地方.

      2.删除从某点开始长为l的一段线段(有可能并不存在,总之就是把这个区间清空).

      输出每次插入操作的位置.

    题目分析

      线段树的经典题,练习块状链表写的好长啊,伤心ing

      用块状链表的话,对于每一个块需要维护以下信息,包含左端点的最长空白,包含右端点的最长空白,这一块内的最长空白及其开始位置,最后是该块是否被完全赋值的标记。

      对于查找操作,我们从头向后查找,维护包含当前块的最长空白长度,注意处理答案存在于块的头部的信息,而且当一个块内有答案时,他不一定是最长空白,需要扫描一遍当前块,从而找到满足条件的最靠前的位置。之后将答案占用的那一段赋成不可用。

      对于整段赋值的操作,头尾两端暴力修改,中间段直接维护标记,之前有标记的要预先下放标记。

      最重要的是当一个块被修改后在sqrt(n)时间内更新信息,左右最大空白段很好维护,对于块内最长空白段,可以用一遍扫描来得到,具体实现只需要维护一个变量表示向前最远的连续空白位置。

      代码比较长,但是很清晰。update是更新块信息,use将一段赋值不可用,blank将一段清空,find查找答案。下标统一从0开始。

    View Code
      1 program hotel(input,output);
      2 var
      3     head,tail:array[0..5000] of longint;
      4     limit,size,n,m:longint;
      5     can:array[0..61000] of boolean;
      6     bj,maxl,maxr,maxp,maxb:array[0..5000] of longint;
      7 procedure build();
      8 var
      9     i:longint;
     10 begin
     11     limit:=trunc(sqrt(n+1));
     12     size:=(n+1) div limit;
     13     if ((n+1) mod limit=0) then
     14         dec(size);
     15     for i:=0 to size do
     16     begin
     17         head[i]:=i*limit;
     18         tail[i]:=(i+1)*limit-1;
     19     end;
     20     tail[size]:=n;
     21     for i:=0 to size do
     22     begin
     23         maxl[i]:=tail[i]-head[i]+1;
     24         maxr[i]:=tail[i]-head[i]+1;
     25         maxp[i]:=tail[i]-head[i]+1;
     26         maxb[i]:=head[i];
     27         bj[i]:=0;
     28     end;
     29 end;{ build }
     30 procedure init;
     31 begin
     32     readln(n,m);
     33     dec(n);
     34     fillchar(can,sizeof(can),true);
     35     build();
     36 end;{ init }
     37 procedure update(now:longint);
     38 var
     39     i,last:longint;
     40 begin
     41     if bj[now]=1 then
     42     begin
     43         maxl[now]:=tail[now]-head[now]+1;
     44         maxr[now]:=tail[now]-head[now]+1;
     45         maxp[now]:=tail[now]-head[now]+1;
     46         maxb[now]:=head[now];
     47         exit;
     48     end;
     49     if bj[now]=-1 then
     50     begin
     51         maxl[now]:=0;
     52         maxr[now]:=0;
     53         maxp[now]:=0;
     54         maxb[now]:=head[now];
     55         exit;
     56     end;
     57     maxl[now]:=tail[now]-head[now]+1;
     58     for i:=head[now] to tail[now] do
     59         if not can[i] then
     60         begin
     61             maxl[now]:=i-head[now];
     62             break;
     63         end;
     64     maxr[now]:=tail[now]-head[now]+1;
     65     for i:=tail[now] downto head[now] do
     66         if (not can[i]) then
     67         begin
     68             maxr[now]:=tail[now]-i;
     69             break;
     70         end;
     71     last:=head[now];
     72     maxp[now]:=0;
     73     maxb[now]:=head[now];
     74     for i:=head[now] to tail[now] do
     75         if not can[i] then
     76         begin
     77             if i-last>maxp[now] then
     78             begin
     79                 maxp[now]:=i-last;
     80                 maxb[now]:=last;
     81             end;
     82             last:=i+1;
     83         end;
     84     if not can[last] then
     85         inc(last);
     86     if tail[now]+1-last>maxp[now] then
     87     begin
     88         maxp[now]:=tail[now]+1-last;
     89         maxb[now]:=last;
     90     end;
     91 end;{ update }
     92 procedure blank(l,r:longint);
     93 var
     94     ll,rr,i:longint;
     95 begin
     96     ll:=l div limit;
     97     rr:=r div limit;
     98     if bj[ll]<>0 then
     99     begin
    100         if bj[ll]=1 then
    101             for i:=head[ll] to tail[ll] do
    102                 can[i]:=true
    103         else
    104             for i:=head[ll] to tail[ll] do
    105                 can[i]:=false;
    106         bj[ll]:=0;
    107     end;
    108     if bj[rr]<>0 then
    109     begin
    110         if bj[rr]=1 then
    111             for i:=head[rr] to tail[rr] do
    112                 can[i]:=true
    113         else
    114             for i:=head[rr] to tail[rr] do
    115                 can[i]:=false;
    116         bj[rr]:=0;
    117     end;    
    118     if ll=rr then
    119     begin
    120         for i:=l to r do
    121             can[i]:=true;
    122         update(ll);
    123         exit;
    124     end;
    125     for i:=l to tail[ll] do
    126         can[i]:=true;
    127     update(ll);
    128     for i:=head[rr] to r do
    129         can[i]:=true;
    130     update(rr);
    131     for i:=ll+1 to rr-1 do
    132     begin
    133         bj[i]:=1;
    134         update(i);
    135     end;
    136 end;{ blank }
    137 procedure use(l,r:longint);
    138 var
    139     ll,rr,i:longint;
    140 begin
    141     ll:=l div limit;
    142     rr:=r div limit;
    143     if bj[ll]<>0 then
    144     begin
    145         if bj[ll]=1 then
    146             for i:=head[ll] to tail[ll] do
    147                 can[i]:=true
    148         else
    149             for i:=head[ll] to tail[ll] do
    150                 can[i]:=false;
    151         bj[ll]:=0;
    152     end;
    153     if bj[rr]<>0 then
    154     begin
    155         if bj[rr]=1 then
    156             for i:=head[rr] to tail[rr] do
    157                 can[i]:=true
    158         else
    159             for i:=head[rr] to tail[rr] do
    160                 can[i]:=false;
    161         bj[rr]:=0;
    162     end;    
    163     if ll=rr then
    164     begin
    165         for i:=l to r do
    166             can[i]:=false;
    167         update(ll);
    168         exit;
    169     end;
    170     for i:=l to tail[ll] do
    171         can[i]:=false;
    172     update(ll);
    173     for i:=head[rr] to r do
    174         can[i]:=false;
    175     update(rr);
    176     for i:=ll+1 to rr-1 do
    177     begin
    178         bj[i]:=-1;
    179         update(i);
    180     end;
    181 end;{ use }
    182 function find(l:longint):longint;
    183 var
    184     i,sum,pp,now,ss:longint;
    185 begin
    186     if maxp[0]>=l then
    187     begin
    188         find:=maxb[0];
    189         now:=head[0];
    190         while now<=tail[0] do
    191         begin
    192             ss:=0;
    193             while (can[now])and(now<=tail[0]) do
    194             begin
    195                 inc(ss);
    196                 inc(now);
    197             end;
    198             if ss>=l then
    199             begin
    200                 find:=now-ss;
    201                 break;
    202             end;
    203             inc(now);
    204         end;
    205         use(find,find+l-1);
    206         exit;
    207     end;
    208     sum:=maxr[0];
    209     pp:=tail[0]-maxr[0]+1;
    210     for i:=1 to size do
    211     begin
    212         if sum+maxl[i]>=l then
    213         begin
    214             find:=pp;
    215             use(pp,pp+l-1);
    216             exit;
    217         end
    218         else
    219         begin
    220             if maxp[i]>=l then
    221             begin
    222                 find:=maxb[i];
    223                 now:=head[i];
    224                 while now<=tail[i] do
    225                 begin
    226                     ss:=0;
    227                     while (can[now])and(now<=tail[i]) do
    228                     begin
    229                         inc(ss);
    230                         inc(now);
    231                     end;
    232                     if ss>=l then
    233                     begin
    234                         find:=now-ss;
    235                         break;
    236                     end;
    237                     inc(now);
    238                 end;
    239                 use(find,find+l-1);
    240                 exit;
    241             end;
    242             if maxl[i]=tail[i]-head[i]+1 then
    243                 sum:=sum+maxl[i]
    244             else
    245             begin
    246                 pp:=tail[i]-maxr[i]+1;
    247                 sum:=maxr[i];
    248             end;
    249         end;
    250     end;
    251     exit(-1);
    252 end;{ find }
    253 procedure main;
    254 var
    255     i,xx,yy,ww:longint;
    256 begin
    257     for i:=1 to m do
    258     begin
    259         read(xx);
    260         if xx=1 then
    261         begin
    262             readln(yy);
    263             writeln(find(yy)+1);
    264         end
    265         else
    266         begin
    267             readln(yy,ww);
    268             blank(yy-1,yy+ww-2);
    269         end;
    270     end;
    271 end;{ main }
    272 begin
    273     init;
    274     main;
    275 end.
  • 相关阅读:
    设计模式的原则
    List是线程安全的吗?如果不是该怎么办呢?安全的List对性能的影响有多大呢?
    StringBuilder是不是线程安全的?
    并行运算和普通运算之性能比较
    分布式与集群的区别
    sql查询性能分析
    C#代码实现,确保windows程序只有一个实例(instance)
    jQuery UI
    开源框架完美组合之Spring.NET + NHibernate + ASP.NET MVC + jQuery + easyUI 中英文双语言小型企业网站Demo
    整理的一些学习网站资料
  • 原文地址:https://www.cnblogs.com/neverforget/p/2748093.html
Copyright © 2020-2023  润新知