POJ2667 Hotel(线段树区间合并)

这类题目会询问区间中满足条件的连续最长区间,所以PushUp的时候需要对左右儿子的区间进行合并

题意:1 a:询问是不是有连续长度为a的空房间,有的话住进最左边
2 a b:将[a,a+b-1]的房间清空
思路:记录区间中最长的空房间
线段树操作:update:区间替换 query:询问满足条件的最左断点

 

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <cmath>
#include <algorithm>
using namespace std;
#define M 50005
#define ls node<<1,l,m
#define rs node<<1|1,m+1,r
int n,m,ltree[M<<2],rtree[M<<2],mtree[M<<2],cover[M<<2];
void pushdown(int node,int m)
{
    if(cover[node]!=-1)
    {
        cover[node<<1]=cover[node<<1|1]=cover[node];
        mtree[node<<1]=ltree[node<<1]=rtree[node<<1]=cover[node]?0:m-(m>>1);
        mtree[node<<1|1]=ltree[node<<1|1]=rtree[node<<1|1]=cover[node]?0:(m>>1);
        cover[node]=-1;
    }
}
void pushup(int node,int m)
{
    ltree[node]=ltree[node<<1];
    rtree[node]=rtree[node<<1|1];
    if(ltree[node]==m-(m>>1)) ltree[node]+=ltree[node<<1|1];
    if(rtree[node]==(m>>1)) rtree[node]+=rtree[node<<1];
    mtree[node]=max(ltree[node<<1|1]+rtree[node<<1],max(mtree[node<<1],mtree[node<<1|1]));
}
void buildtree(int node,int l,int r)
{
    mtree[node]=ltree[node]=rtree[node]=r-l+1;
    cover[node]=-1;
    if(l==r) return ;
    int m=(l+r)>>1;
    buildtree(ls);
    buildtree(rs);
}
void update(int L,int R,int c,int node,int l,int r)
{
    if(L<=l&&r<=R)
    {
        mtree[node]=ltree[node]=rtree[node]=c?0:r-l+1;
        cover[node]=c;
        return ;
    }
    pushdown(node,r-l+1);
    int m=(l+r)>>1;
    if(L<=m) update(L,R,c,ls);
    if(m<R) update(L,R,c,rs);
    pushup(node,r-l+1);
}
int query(int node,int l,int r,int w)
{
    if(l==r) return l;
    pushdown(node,r-l+1);
    int m=(l+r)>>1;
    if(mtree[node<<1]>=w) return query(ls,w);
    else if(rtree[node<<1]+ltree[node<<1|1]>=w) return (m-rtree[node<<1]+1);
    return query(rs,w);
}
int main()
{
    //freopen("in.txt","r",stdin);
    scanf("%d%d",&n,&m);
    buildtree(1,1,n);
    while(m--)
    {
        int op,a,b;
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%d",&a);
            if(mtree[1]<a) printf("0\n");
            else
            {
                int p=query(1,1,n,a);
                printf("%d\n",p);
                update(p,p+a-1,1,1,1,n);
            }
        }
        else
        {
            scanf("%d%d",&a,&b);
            update(a,a+b-1,0,1,1,n);
        }
    }
    return 0;
}

 

posted on 2015-08-22 12:17  恶devil魔  阅读(210)  评论(0编辑  收藏  举报

导航