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

题目传送门

/*
    题意:输入 1 a:询问是不是有连续长度为a的空房间,有的话住进最左边
            输入 2 a b:将[a,a+b-1]的房间清空
    线段树(区间合并):lsum[]统计从左端点起最长连续空房间数,rsum[]类似,sum[]统计区间最长连续的空房间数,
            它有三种情况:1.纯粹是左端点起的房间数;2.纯粹是右端点的房间数;3.当从左(右)房间起都连续时,加上另一个子节点
            从左(右)房间起的数,sum[]再求最大值更新维护。理解没错,表达能力不足
    详细解释:http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html
*/
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
const int MAXN = 5e4 + 10;
const int INF = 0x3f3f3f3f;
struct Segment_Tree {
    int sum[MAXN<<2], lsum[MAXN<<2], rsum[MAXN<<2], cover[MAXN<<2];
    void push_up(int rt, int len)    {
        lsum[rt] = lsum[rt<<1];
        rsum[rt] = rsum[rt<<1|1];
        if (lsum[rt] == len - (len>>1)) lsum[rt] += lsum[rt<<1|1];
        if (rsum[rt] == len>>1)   rsum[rt] += rsum[rt<<1];
        sum[rt] = max (rsum[rt<<1] + lsum[rt<<1|1], max (sum[rt<<1], sum[rt<<1|1]));
    }
    void push_down(int rt, int len) {
        if (cover[rt] != -1)    {
            cover[rt<<1] = cover[rt<<1|1] = cover[rt];
            sum[rt<<1] = lsum[rt<<1] = rsum[rt<<1] = cover[rt] ? 0 : len - (len>>1);
            sum[rt<<1|1] = lsum[rt<<1|1] = rsum[rt<<1|1] = cover[rt] ? 0 : len >> 1;
            cover[rt] = -1;
        }
    }
    void build(int l, int r, int rt)    {
        sum[rt] = lsum[rt] = rsum[rt] = r - l + 1;
        cover[rt] = -1;
        if (l == r) return ;
        int mid = (l + r) >> 1;
        build (lson);   build (rson);
    }
    void updata(int ql, int qr, int c, int l, int r, int rt)   {
        if (ql <= l && r <= qr) {
            sum[rt] = lsum[rt] = rsum[rt] = c ? 0 : (r - l + 1);
            cover[rt] = c;  return ;
        }
        push_down (rt, r - l + 1);
        int mid = (l + r) >> 1;
        if (ql <= mid)  updata (ql, qr, c, lson);
        if (qr > mid)   updata (ql, qr, c, rson);
        push_up (rt, r - l + 1);
    }
    int query(int w, int l, int r, int rt) {
        if (l == r) return l;
        push_down (rt, r - l + 1);
        int mid = (l + r) >> 1;
        if (sum[rt<<1] >= w)    return query (w, lson);
        else if (rsum[rt<<1] + lsum[rt<<1|1] >= w)  return mid - rsum[rt<<1] + 1;
        else    return query (w, rson);
    }
}st;

int main(void)  {       //POJ 3667 Hotel
    int n, m;
    while (scanf ("%d%d", &n, &m) == 2) {
        st.build (1, n, 1);
        for (int i=1; i<=m; ++i)    {
            int op, a, b; scanf ("%d%d", &op, &a);
            if (op == 1)    {
                if (st.sum[1] < a)  puts ("0");
                else    {
                    int p = st.query (a, 1, n, 1);
                    printf ("%d
", p);
                    st.updata (p, p + a - 1, 1, 1, n, 1);
                }
            }
            else    {
                scanf ("%d", &b);
                st.updata (a, a + b - 1, 0, 1, n, 1);
            }
        }
    }

    return 0;
}

  

编译人生,运行世界!
原文地址:https://www.cnblogs.com/Running-Time/p/4686455.html