• 博客园logo
  • 会员
  • 周边
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
魂之挽歌
博客园    首页    新随笔    联系   管理    订阅  订阅

POJ3667 HOTEL

POJ3667 HOTEL

【题目大意】

     有一个旅馆,有N个房间排成一排,现在有两种操作,第一是有X个顾客要入住连续的X个房间,要求输出最小的左端点的位置,不能满足就输出0,第二是将以l开始,长度为X的连续房间清空。

【输入文件】

     第一行两个数N,M,表示房间数和操作数

     接下来M行,每行有两种情况:

     1 X 表示操作1

     2 l X 表示操作2

【输出文件】

     对于每一个1操作,输出答案。

【输入样例】

10 6

1 3

1 3

1 3

1 3

2 5 5

1 6

【输出样例】

1

4

7

0

5

【题目分析】

     方案一:线段树

     首先最经典的是线段树的做法,在每个节点上新加3个域Z,Y,S,Z表示区间左边连续的空房个数,Y表示区间有边连续的空房个数,S表示区间上最大的一段空房的长度。

     那么:

      A[i].z:=a[a[i].l].z(左区间不都为空时)

            A[a[i].l].len+a[a[i].r].z(左区间为空时)

      A[i].y类似。

      A[i].s:=max(a[a[i].l].s,a[a[i].r].s,a[a[i].l].y+a[a[i].r].z)

     插入和删除线段时要用到lazy操作

     查询时:

        1、如果1~n区间的S值都比X小,就无解,否则有解。

        2、对于每一个区间,如果它的左儿子的S值大于等于X,到左儿子里去找。

        3、如果左儿子的Y加上有儿子的Z大于等于X,直接返回左儿子的右端点减去左儿子的Y值。

        4、否则到右儿子里去找。

        5、如果满足2,则不再考虑3,4;同样,满足3就不再考虑4。

     

Code 1
  1 program poj3667;
  2 type tree=record
  3       a,b,l,r,z,y,s,bj:longint;
  4      end;
  5 var a:array[0..100000]of tree;
  6     i,j,m,n,k,x,tot,ans,p,l,r:longint;
  7 procedure make(l,r:longint);
  8 var mid,now:longint;
  9 begin
 10     inc(tot);
 11     a[tot].a:=l;
 12     a[tot].b:=r;
 13     a[tot].z:=r-l;
 14     a[tot].y:=r-l;
 15     a[tot].s:=r-l;
 16     mid:=(l+r)shr 1;
 17     if l<mid then
 18     begin
 19         now:=tot;
 20         a[now].l:=tot+1;
 21         make(l,mid);
 22         a[now].r:=tot+1;
 23         make(mid,r);
 24     end;
 25 end;
 26 function max(a,b:longint):longint;
 27 begin
 28     if a>b then exit(a)
 29     else exit(b);
 30 end;
 31 procedure calc(i:longint);
 32 begin
 33     if a[a[i].l].z=a[a[i].l].b-a[a[i].l].a then a[i].z:=a[a[i].l].z+a[a[i].r].z
 34     else a[i].z:=a[a[i].l].z;
 35     if a[a[i].r].y=a[a[i].r].b-a[a[i].r].a then a[i].y:=a[a[i].r].y+a[a[i].l].y
 36     else a[i].y:=a[a[i].r].y;
 37     a[i].s:=max(max(a[a[i].l].s,a[a[i].r].s),a[a[i].l].y+a[a[i].r].z);
 38 end;
 39 procedure clean(i:longint);
 40 begin
 41     a[a[i].l].bj:=a[i].bj;
 42     a[a[i].r].bj:=a[i].bj;
 43     if a[i].bj=1 then
 44     begin
 45         a[a[i].l].z:=0;
 46         a[a[i].r].z:=0;
 47         a[a[i].l].y:=0;
 48         a[a[i].r].y:=0;
 49         a[a[i].l].s:=0;
 50         a[a[i].r].s:=0;
 51     end
 52     else
 53     begin
 54         a[a[i].l].z:=a[a[i].l].b-a[a[i].l].a;
 55         a[a[i].r].z:=a[a[i].r].b-a[a[i].r].a;
 56         a[a[i].l].y:=a[a[i].l].b-a[a[i].l].a;
 57         a[a[i].r].y:=a[a[i].r].b-a[a[i].r].a;
 58         a[a[i].l].s:=a[a[i].l].b-a[a[i].l].a;
 59         a[a[i].r].s:=a[a[i].r].b-a[a[i].r].a;
 60     end;
 61     a[i].bj:=0;
 62 end;
 63 procedure insert(i,l,r:longint);
 64 var mid:longint;
 65 begin
 66     if (l<=a[i].a)and(a[i].b<=r) then
 67     begin
 68         a[i].z:=0;
 69         a[i].y:=0;
 70         a[i].s:=0;
 71         a[i].bj:=1;
 72         exit;
 73     end;
 74     mid:=(a[i].a+a[i].b)shr 1;
 75     if a[i].bj<>0 then clean(i);
 76     if l<mid then insert(a[i].l,l,r);
 77     if mid<r then insert(a[i].r,l,r);
 78     calc(i);
 79 end;
 80 procedure delete(i,l,r:longint);
 81 var mid:longint;
 82 begin
 83     if (l<=a[i].a)and(a[i].b<=r) then
 84     begin
 85         a[i].z:=a[i].b-a[i].a;
 86         a[i].y:=a[i].b-a[i].a;
 87         a[i].s:=a[i].b-a[i].a;
 88         a[i].bj:=-1;
 89         exit;
 90     end;
 91     mid:=(a[i].a+a[i].b)shr 1;
 92     if a[i].bj<>0 then clean(i);
 93     if l<mid then delete(a[i].l,l,r);
 94     if mid<r then delete(a[i].r,l,r);
 95     calc(i);
 96 end;
 97 function get(i,x:longint):longint;
 98 var mid:longint;
 99 begin
100     if a[i].s<x then exit(0);
101     if a[i].bj<>0 then clean(i);
102     if a[a[i].l].s>=x then exit(get(a[i].l,x));
103     if a[a[i].l].y+a[a[i].r].z>=x then exit(a[a[i].l].b-a[a[i].l].y+1);
104     exit(get(a[i].r,x));
105 end;
106 begin
107     readln(n,m);
108     make(0,n);
109     for i:=1 to m do
110     begin
111         read(k);
112         if k=1 then
113         begin
114             readln(x);
115             l:=get(1,x);
116             writeln(l);
117             r:=l+x-1;
118             if l<>0 then insert(1,l-1,r);
119         end
120         else
121         begin
122             readln(l,r);
123             r:=l+r-1;
124             delete(1,l-1,r);
125         end;
126     end;
127 end.

 

      方案二:链表

      首先表示这个方法不是自己想的,是小银月亮童鞋想出来的。

      搞一个链表,链表的每个元素是一段连续空房的区间,查询时找到第一个长度足够的区间,然后更新这个区间的左右端点或直接将该区间删除,增加空房时就将给出的区间与原有区间合并。

      这个方法的理论复杂度是N^2的,对于随机数据常数较小,但是还是能被一些数据能卡住。

      事实证明,这个方法对付POJ的数据绰绰有余,上面的线段树方法454ms,链表的做法344ms

 

Code 2
 1 program poj3667_2;
 2 type lian=record
 3       l,r,last,next:longint;
 4      end;
 5 var a:array[0..100000]of lian;
 6     i,j,m,n,k,x,l,r,tot,tp:longint;
 7 function max(a,b:longint):longint;
 8 begin
 9     if a>b then exit(a)
10     else exit(b);
11 end;
12 function min(a,b:longint):longint;
13 begin
14     if a<b then exit(a)
15     else exit(b);
16 end;
17 begin
18     readln(n,m);
19     a[0].l:=0;a[0].r:=-1;a[0].next:=1;a[0].last:=-1;
20     a[1].l:=1;a[1].r:=n;a[1].next:=2;a[1].last:=0;
21     a[2].l:=n+2;a[2].r:=n+1;a[2].last:=1;a[2].next:=-1;
22     tot:=2;
23     for tp:=1 to m do
24     begin
25         read(k);
26         if k=1 then
27         begin
28             readln(x);
29             i:=0;
30             while (i<>-1)and(a[i].r-a[i].l+1<x) do i:=a[i].next;
31             if i=-1 then
32             begin
33                 writeln(0);
34                 continue;
35             end;
36             writeln(a[i].l);
37             if a[i].r-a[i].l+1=x then
38             begin
39                 a[a[i].last].next:=a[i].next;
40                 a[a[i].next].last:=a[i].last;
41             end
42             else a[i].l:=a[i].l+x;
43         end
44         else
45         begin
46             readln(l,r);
47             r:=l+r-1;
48             i:=0;
49             while a[a[i].next].r+1<l do i:=a[i].next;
50             j:=i;
51             while a[j].l<=r+1 do j:=a[j].next;
52             inc(tot);
53             a[tot].l:=min(l,a[a[i].next].l);
54             a[tot].r:=max(r,a[a[j].last].r);
55             a[tot].next:=j;
56             a[tot].last:=i;
57             a[i].next:=tot;
58             a[j].last:=tot;
59         end;
60     end;
61 end.

 

 

 

posted @ 2012-05-25 09:14  魂之挽歌  阅读(1063)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3