码迷,mamicode.com
首页 > 其他好文 > 详细

线段树(区间合并) POJ 3667 Hotel

时间:2015-07-29 19:06:28      阅读:135      评论:0      收藏:0      [点我收藏+]

标签:

 

题目传送门

 1 /*
 2     题意:输入 1 a:询问是不是有连续长度为a的空房间,有的话住进最左边
 3             输入 2 a b:将[a,a+b-1]的房间清空
 4     线段树(区间合并):lsum[]统计从左端点起最长连续空房间数,rsum[]类似,sum[]统计区间最长连续的空房间数,
 5             它有三种情况:1.纯粹是左端点起的房间数;2.纯粹是右端点的房间数;3.当从左(右)房间起都连续时,加上另一个子节点
 6             从左(右)房间起的数,sum[]再求最大值更新维护。理解没错,表达能力不足
 7     详细解释:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html
 8 */
 9 #include <cstdio>
10 #include <algorithm>
11 #include <cstring>
12 using namespace std;
13 
14 #define lson l, mid, rt << 1
15 #define rson mid + 1, r, rt << 1 | 1
16 const int MAXN = 5e4 + 10;
17 const int INF = 0x3f3f3f3f;
18 struct Segment_Tree {
19     int sum[MAXN<<2], lsum[MAXN<<2], rsum[MAXN<<2], cover[MAXN<<2];
20     void push_up(int rt, int len)    {
21         lsum[rt] = lsum[rt<<1];
22         rsum[rt] = rsum[rt<<1|1];
23         if (lsum[rt] == len - (len>>1)) lsum[rt] += lsum[rt<<1|1];
24         if (rsum[rt] == len>>1)   rsum[rt] += rsum[rt<<1];
25         sum[rt] = max (rsum[rt<<1] + lsum[rt<<1|1], max (sum[rt<<1], sum[rt<<1|1]));
26     }
27     void push_down(int rt, int len) {
28         if (cover[rt] != -1)    {
29             cover[rt<<1] = cover[rt<<1|1] = cover[rt];
30             sum[rt<<1] = lsum[rt<<1] = rsum[rt<<1] = cover[rt] ? 0 : len - (len>>1);
31             sum[rt<<1|1] = lsum[rt<<1|1] = rsum[rt<<1|1] = cover[rt] ? 0 : len >> 1;
32             cover[rt] = -1;
33         }
34     }
35     void build(int l, int r, int rt)    {
36         sum[rt] = lsum[rt] = rsum[rt] = r - l + 1;
37         cover[rt] = -1;
38         if (l == r) return ;
39         int mid = (l + r) >> 1;
40         build (lson);   build (rson);
41     }
42     void updata(int ql, int qr, int c, int l, int r, int rt)   {
43         if (ql <= l && r <= qr) {
44             sum[rt] = lsum[rt] = rsum[rt] = c ? 0 : (r - l + 1);
45             cover[rt] = c;  return ;
46         }
47         push_down (rt, r - l + 1);
48         int mid = (l + r) >> 1;
49         if (ql <= mid)  updata (ql, qr, c, lson);
50         if (qr > mid)   updata (ql, qr, c, rson);
51         push_up (rt, r - l + 1);
52     }
53     int query(int w, int l, int r, int rt) {
54         if (l == r) return l;
55         push_down (rt, r - l + 1);
56         int mid = (l + r) >> 1;
57         if (sum[rt<<1] >= w)    return query (w, lson);
58         else if (rsum[rt<<1] + lsum[rt<<1|1] >= w)  return mid - rsum[rt<<1] + 1;
59         else    return query (w, rson);
60     }
61 }st;
62 
63 int main(void)  {       //POJ 3667 Hotel
64     int n, m;
65     while (scanf ("%d%d", &n, &m) == 2) {
66         st.build (1, n, 1);
67         for (int i=1; i<=m; ++i)    {
68             int op, a, b; scanf ("%d%d", &op, &a);
69             if (op == 1)    {
70                 if (st.sum[1] < a)  puts ("0");
71                 else    {
72                     int p = st.query (a, 1, n, 1);
73                     printf ("%d\n", p);
74                     st.updata (p, p + a - 1, 1, 1, n, 1);
75                 }
76             }
77             else    {
78                 scanf ("%d", &b);
79                 st.updata (a, a + b - 1, 0, 1, n, 1);
80             }
81         }
82     }
83 
84     return 0;
85 }

 

线段树(区间合并) POJ 3667 Hotel

标签:

原文地址:http://www.cnblogs.com/Running-Time/p/4686455.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!