POJ3667

题目链接:http://poj.org/problem?id=3667

题意:1 a:询问是不是有连续长度为a的空房间,有的话住进最左边
2 a b:[a,a+b-1]的房间清空
思路:记录区间中最长的空房间

#include <iostream>
#include <cstdio>
#define lson l, m, x<<1
#define rson m+1, r, x<<1|1
using namespace std;


const int INF = (1<<31)-1;
const int maxn = 55555;


int lsum[maxn<<2], rsum[maxn<<2], sum[maxn<<2];
int cover[maxn<<2];


void pushUp(int x, int m)
{
    sum[x] = max(sum[x<<1], sum[x<<1|1]);
    sum[x] = max(sum[x], rsum[x<<1] + lsum[x<<1|1]);
    lsum[x] = lsum[x<<1];
    rsum[x] = rsum[x<<1|1];
    if (lsum[x] == (m-(m>>1)))
        lsum[x] += lsum[x<<1|1];
    if (rsum[x] == (m>>1))
        rsum[x] += rsum[x<<1];
}


void pushDown(int x, int m)
{
    if (cover[x] != -1)
    {
        int lpos = x<<1;
        int rpos = x<<1|1;
        cover[lpos] = cover[rpos] = cover[x];
        sum[lpos] = lsum[lpos] = rsum[lpos] = cover[x] ? 0 : (m-(m>>1));
        sum[rpos] = lsum[rpos] = rsum[rpos] = cover[x] ? 0 : (m>>1);
        cover[x] = -1;
    }
}


void build(int l, int r, int x)
{
    sum[x] = lsum[x] = rsum[x] = r-l+1;
    cover[x] = -1;
    if (l == r)
    {
        return ;
    }


    int m = (l + r) >> 1;
    build(lson);
    build(rson);
}


void update(int l, int r, int x, int L, int R, int C)
{
    if (L <= l && r <= R)
    {
        sum[x] = lsum[x] = rsum[x] = (r-l+1)*(1-C);
        cover[x] = C;
        return ;
    }
    pushDown(x, r-l+1);
    int m = (l+r) >> 1;
    if (L <= m) update(lson, L, R, C);
    if (R >  m) update(rson, L, R, C);
    pushUp(x, r-l+1);
}


int query(int l, int r, int x, int a)
{
    if (l == r)
    {
        return l;
    }
    pushDown(x, r-l+1);
    int m = (l+r) >> 1;
    if (sum[x<<1] >= a)
        return query(lson, a);
    else if (rsum[x<<1] + lsum[x<<1|1] >= a)
        return m - rsum[x<<1] + 1;
    else
        return query(rson, a);
}


int main()
{
    int n, m;
    scanf("%d%d", &n,&m);
    build(1, n, 1);
    while (m > 0)
    {
        m--;


        int op, a, b;
        scanf("%d", &op);
        if (op == 1)
        {
            scanf("%d", &a);
            if (sum[1] < a)
                puts("0");
            else
            {
                int p = query(1, n, 1, a);
                printf("%d\n", p);
                update(1, n, 1, p, p+a-1, 1);
            }
        }
        else
        {
            scanf("%d%d", &a, &b);
            update(1, n, 1, a, a+b-1, 0);
        }
    }


    return 0;
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值