POJ 3667 Hotel(线段树区间合并)

题意:

[1,N]区间内开始为空,有两种操作1) 1 a 找到长度为a的区间,并且尽量开头靠左,返回最左的位置并check in. 2) 2 a b 将[a,b-1]区间check out.

思路:

线段树-区间合并,对于每个节点记录三个值.1).lsum表示该节点区间从左边开始的空的区间长度2).rsum表示该节点区间从右到左开始空的区间长度3).sum表示该节点区间最长的空的区间长度

进行push_down的操作的时候,对于laz标记,看该区间是何标记,并将其两个子区间标记为相应值,对于push_up操作.更新其节点的三个值

lsum[rt] 置为左儿子的lsum值.如果左儿子该区间的lsum就是左儿子的区间长度,那么就可以加上右儿子的lsum值了

rsum[rt] 置为右儿子的rsum值.如果右儿子该区间的rsum就是右儿子的区间长度,那么就可以加上左儿子的rsum值了

sum[rt] 是左儿子的sum的值,右儿子的sum的值,中间一段sum的值的最大取值.

#include<iostream>
#include<algorithm>
#include<cstdio>
#define ls (rt<<1)
#define rs (rt<<1|1)
 using namespace std;
 const int maxn=5e4+10;
 struct node{
     int lsum,rsum,sum,cover;
 }hotel[maxn<<2];
 struct Segment_Tree{
     void pushUp(int rt,int m)
     {
         hotel[rt].lsum=hotel[ls].lsum;
         hotel[rt].rsum=hotel[rs].rsum;
         if(hotel[rt].lsum==m-(m>>1))
             hotel[rt].lsum+=hotel[rs].lsum;
         if(hotel[rt].rsum==(m>>1))
             hotel[rt].rsum+=hotel[ls].rsum;
         hotel[rt].sum=max(hotel[ls].rsum+hotel[rs].lsum,max(hotel[ls].sum,hotel[rs].sum));
     }
     void pushDown(int rt,int len)
     {
         if(hotel[rt].cover!=-1){
             hotel[rs].cover=hotel[ls].cover=hotel[rt].cover;
             hotel[ls].lsum=hotel[ls].rsum=hotel[ls].sum=hotel[ls].cover?0:len-(len>>1);
             hotel[rs].lsum=hotel[rs].rsum=hotel[rs].sum=hotel[rs].cover?0:(len>>1);
             hotel[rt].cover=-1;
         }
     }
     void build(int l,int r,int rt)
     {
         hotel[rt].lsum=hotel[rt].rsum=hotel[rt].sum=r-l+1;
         hotel[rt].cover=-1;
         if(l==r) return;
        int mid=(l+r)>>1;
        build(l,mid,ls);
        build(mid+1,r,rs);         
     }
    void update(int L,int R,int C,int l,int r,int rt)
    {
        if(L<=l&&r<=R){
            hotel[rt].cover=C;
            hotel[rt].sum=hotel[rt].lsum=hotel[rt].rsum=hotel[rt].cover?0:r-l+1;
            return;
        }
        int m=(l+r)>>1;
        pushDown(rt,r-l+1);
        if(L<=m) update(L,R,C,l,m,ls);
        if(R>m)  update(L,R,C,m+1,r,rs);
        pushUp(rt,r-l+1); 
    }
    int query(int w,int l,int r,int rt)
    {
        if(l==r) return l;
        pushDown(rt,r-l+1);
        int mid=(l+r)>>1;
        if(hotel[ls].sum>=w) return query(w,l,mid,ls);
        else if(hotel[ls].rsum+hotel[rs].lsum>=w)
            return mid-hotel[ls].rsum+1;
        return query(w,mid+1,r,rs);
    }
 }T;
 int main()
 {
     int n,k,op,len,s;
     while(scanf("%d%d",&n,&k)!=EOF){
         T.build(1,n,1);
         for(int i=1;i<=k;i++){
             scanf("%d",&op);
             if(op==1){
                 scanf("%d",&len);
                 if(hotel[1].sum<len){
                     cout<<0<<endl;
                     continue;
                 }
                s=T.query(len,1,n,1);
                cout<<s<<endl;
                T.update(s,s+len-1,1,1,n,1);
             }
             else{
                 scanf("%d%d",&s,&len);
                 T.update(s,s+len-1,0,1,n,1);
             }
         }
     }
    return 0;
 }
View Code

猜你喜欢

转载自www.cnblogs.com/overrate-wsj/p/12411960.html
今日推荐