POJ 1823 Hotel(线段树区间更新)

本文介绍了一个使用线段树实现的酒店房间管理系统算法。该算法能够高效处理房间占用、释放及查询连续空房间的最大数量等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

一个Hotel有N个房间,一开始全部为空。
接下来有M个询问。
输入1,代表房间被占用,然后输入两个数代表房间被占用的房间号和数量。
输入2,代表房间被置空,输入两个数代表房间被清空的房间号和数量。
输入3,输出连续最长没有被占用的房间数量。

思路:

线段树的区间更新,维护的值还是很好想的,
分别是当前
线段的maxl最长连续的左区间,maxr最长连续右区间,maxv最大值。
但是懒惰标记不好想,调试了很久都没有结果,后来参考了一段别人的代码,加上自己的理解,终于A了。
懒惰标记上面有3个值 0表示空,1表示满,-1表示非满非空。
然后根据这3个标记维护线段树。

my code

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ls (o<<1)
#define rs (o<<1|1)
using namespace std;
const int N = 16005;

struct Node {
    int maxl, maxr, maxv;
    int cover; //0表示空,1表示满,-1表示非满非空
    void calc(int L, int R) {
        if(cover == 1) //如果满,全部置为0
            maxl = maxr = maxv = 0;
        else if(cover == 0) //如果空,最长长度=区间长度
            maxl = maxr = maxv = (R-L+1);
    }
} node[N<<2];

void pushUp(int o, int L, int R) {
    int M = (L+R)/2;
    int lenL = (M-L+1), lenR = (R-M);
    if(node[ls].maxl == lenL) node[o].maxl = node[ls].maxv + node[rs].maxl;
    else node[o].maxl = node[ls].maxl;

    if(node[rs].maxr == lenR) node[o].maxr = node[rs].maxv + node[ls].maxr;
    else node[o].maxr = node[rs].maxr;

    node[o].maxv = (node[ls].maxr + node[rs].maxl);
    node[o].maxv = max(node[o].maxv, max(node[ls].maxv, node[rs].maxv));

    if(node[ls].cover == node[rs].cover)
        node[o].cover = node[ls].cover;
    else
        node[o].cover = -1;
}

void pushDown(int o, int L, int R) {
    if(node[o].cover == -1) return;
    node[ls].cover = node[rs].cover = node[o].cover;
    node[o].cover = -1;
    int M = (L+R)/2;
    node[ls].calc(L, M);
    node[rs].calc(M+1, R);
}

void build(int o, int L, int R) {
    if(L == R) {
        node[o].cover = 0;
        node[o].calc(L, R);
        return ;
    }
    int M = (L+R)/2;
    build(ls, L, M);
    build(rs, M+1, R);
    pushUp(o, L, R);
}

int ql, qr, op;
void modify(int o, int L, int R) {
    if(ql <= L && R <= qr) {
        if(op == 1) node[o].cover = 1;
        else node[o].cover = 0;
        node[o].calc(L, R);
        return ;
    }
    pushDown(o, L, R);
    int M = (L+R)/2;
    if(ql <= M) modify(ls, L, M);
    if(qr > M) modify(rs, M+1, R);
    pushUp(o, L, R);
}

int n, m;
int main() {
    //freopen("in.txt", "r", stdin);
    while(scanf("%d%d", &n, &m) != EOF) {
        build(1, 1, n);
        int x, y;
        while(m--) {
            scanf("%d", &op);
            if(op == 1 || op == 2) {
                scanf("%d%d", &x, &y);
                ql = x, qr = x+y-1;
                modify(1, 1, n);
            }else {
                printf("%d\n", node[1].maxv);
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值