Poj 3667 Hotel

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

本题也是线段树区间合并问题。和上一题LCIS类似。

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

#include <iostream>
#include <stdlib.h>
#include <stdio.h>

using namespace std;

#define Maxn 50005
#define lx (x<<1)
#define rx ((x<<1)|1)
#define MID ((l + r)>>1)

int A[Maxn];
//记录连续空房间的最大个数
int midSum[Maxn<<2];
int leftSum[Maxn<<2];
int rightSum[Maxn<<2];
//标记是否被覆盖
int cover[Maxn<<2];
void pushDown(int l,int r,int x)
{
    if(cover[x]!=-1)
    {
        int m = (r - l + 1);
        cover[lx] = cover[rx] = cover[x];
        //被占用
        if(cover[x] == 1)
        {
            midSum[lx] = leftSum[lx] = rightSum[lx] = 0;
            midSum[rx] = leftSum[rx] = rightSum[rx] = 0;
        }
        //未被占用
        else
        {
            midSum[lx] = leftSum[lx] = rightSum[lx] = m - (m>>1);
            midSum[rx] = leftSum[rx] = rightSum[rx] = (m>>1);
        }
		cover[x] = -1;
    }
}
void pushUp(int l,int r,int x)
{
    int m = r - l + 1;
    leftSum[x] = leftSum[lx];
    rightSum[x] = rightSum[rx];
	if(leftSum[x] == m-(m>>1)) leftSum[x] += leftSum[rx];
	if(rightSum[x] == (m >> 1)) rightSum[x] += rightSum[lx];
	midSum[x] = max(leftSum[rx] + rightSum[lx],max(midSum[lx],midSum[rx]));
}
void build(int l,int r,int x)
{
    cover[x] = -1;
    midSum[x] = leftSum[x] = rightSum[x] =  (r - l + 1);
    if(l == r) return;
    build(l,MID,lx);
    build(MID+1,r,rx);
}
void update(int L,int R,int d,int l,int r,int x)
{
    if(L<=l && r<=R)
    {
        cover[x] = d;
        if(d == 0) midSum[x] = leftSum[x] = rightSum[x] = r-l+1;
        else midSum[x] = leftSum[x] = rightSum[x] = 0;
        return;
    }
    pushDown(l,r,x);
    if(L<=MID) update(L,R,d,l,MID,lx);
    if(MID+1<=R) update(L,R,d,MID+1,r,rx);
    pushUp(l,r,x);
}

int query(int w,int l,int r,int x)
{
    if (l == r) return l;
    pushDown(l,r,x);
    if(w<=midSum[lx]) return query(w,l,MID,lx);
    else if(w<=rightSum[lx] + leftSum[rx]) return (MID - rightSum[lx] + 1);
    else return query(w,MID+1,r,rx);
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif
    int n,m;
    int op;
    int d,x;
    scanf(" %d %d",&n,&m);
    build(1,n,1);
    for(int i=0;i<m;i++)
    {
        scanf(" %d",&op);
        if(op == 1)
        {
            scanf(" %d",&d);
            if(midSum[1]<d) puts("0");
            else
            {
                int p = query(d,1,n,1);
                printf("%d\n",p);
                update(p,p+d-1,1,1,n,1);
            }
        }
        else
        {
            scanf(" %d %d",&x,&d);
            update(x,x+d-1,0,1,n,1);
        }
    }
    return 0;
}


你可能感兴趣的:(Poj 3667 Hotel)