POJ 3667 Hotel 线段树区间合并

76 篇文章 0 订阅
32 篇文章 0 订阅

这道题应该算是比较经典的线段树了

题意是:

这座巨型宾馆在一条超长走廊上有N(1 ≤ N ≤ 50000)个排成一排的房间,每个房间都能欣赏到苏必利尔湖的好景色。现在所有的房间都是空的。


现在Bessie等旅客们正在不断地发出订房和退房要求。你需要接受M(1 ≤ M < 50000)条指令:


每条指令的第一个数字为1或2。如果是1,后面将有一个整数D表示顾客要预定的房间数。注意,这些房间必须是连续的。如果能够满足旅客的订房要求, 输出满足要求的第一个房间的编号(例如,要订房6间,输出3表示3, 4, 5, 6, 7, 8是满足要求的),这样的编号必须是可能的编号里面最靠前的。如果不能满足要求,输出0。


如果是2,后面将有两个整数X和D表示顾客要退掉X, X + 1, X + 2, ... , X + D - 1这D间房。对于这样的指令什么都不输出

线段树保存的信息有,cover代表是否有人,msum代表区间内最大的连续长度,lsum是从左结点往右的连续长度,rsum是从右结点往左的连续长度。


/*
ID: sdj22251
PROG: inflate
LANG: C++
*/
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cmath>
#include <ctime>
#define MAXN 50005
#define INF 10000000000000000LL
#define L(x) x<<1
#define R(x) x<<1|1
#define PI acos(-1.0)
#define eps 1e-7
using namespace std;
struct node
{
    int left, right, mid;
    int cover, lsum, rsum, msum;
}tree[4 * MAXN];
void down(int C)
{
    if(tree[C].cover != -1)
    {
        int p = tree[C].right - tree[C].left + 1;
        tree[L(C)].cover = tree[R(C)].cover = tree[C].cover;
        tree[L(C)].lsum = tree[L(C)].rsum = tree[L(C)].msum = tree[C].cover ? 0 : p - (p >> 1);
        tree[R(C)].lsum = tree[R(C)].rsum = tree[R(C)].msum = tree[C].cover ? 0 : (p >> 1);
        tree[C].cover = -1;
    }
}
void up(int C)
{
    int p = tree[C].right - tree[C].left + 1;
    tree[C].lsum = tree[L(C)].lsum;
    tree[C].rsum = tree[R(C)].rsum;
    if(tree[C].lsum == p - (p >> 1)) tree[C].lsum += tree[R(C)].lsum;
    if(tree[C].rsum == (p >> 1)) tree[C].rsum += tree[L(C)].rsum;
    tree[C].msum = max(tree[R(C)].lsum + tree[L(C)].rsum, max(tree[L(C)].msum, tree[R(C)].msum));
}
void make_tree(int s, int e, int C)
{
    tree[C].left = s;
    tree[C].right = e;
    tree[C].mid = (s + e) >> 1;
    tree[C].cover = -1;
    tree[C].lsum = tree[C].rsum = tree[C].msum = e - s + 1;
    if(s == e) return;
    make_tree(s, tree[C].mid, L(C));
    make_tree(tree[C].mid + 1, e, R(C));
}
void update(int s, int e, int p, int C)
{
    if(tree[C].left >= s && tree[C].right <= e)
    {
        tree[C].msum = tree[C].lsum = tree[C].rsum = p ? 0: tree[C].right - tree[C].left + 1;
        tree[C].cover = p;
        return;
    }
    down(C);
    if(tree[C].mid >= s) update(s, e, p, L(C));
    if(tree[C].mid < e) update(s, e, p, R(C));
    up(C);
}
int query(int p, int C)
{
    if(tree[C].left == tree[C].right) return tree[C].left;
    down(C);
    if(tree[L(C)].msum >= p) return query(p, L(C));
    else if(tree[L(C)].rsum + tree[R(C)].lsum >= p) return tree[C].mid - tree[L(C)].rsum + 1;
    else return query(p, R(C));
}
int main()
{
    int n, m, op, x, y;
    scanf("%d%d", &n, &m);
    make_tree(1, n, 1);
    while(m--)
    {
        scanf("%d", &op);
        if(op == 1)
        {
            scanf("%d", &x);
            if(tree[1].msum < x) puts("0");
            else
            {
                int p = query(x, 1);
                printf("%d\n", p);
                update(p, p + x - 1, 1, 1);
            }
        }
        else
        {
            scanf("%d%d", &x, &y);
            update(x, x + y - 1, 0, 1);
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值