zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Leetcode888. 公平的糖果棒交换
    Leetcode81. 搜索旋转排序数组 II
    Leetcode80. 删除排序数组中的重复项 II
    Leetcode1631. 最小体力消耗路径
    Leetcode57. 插入区间
    Leetcode724. 寻找数组的中心索引
    Leetcode18. 四数之和
    Leetcode110. 平衡二叉树
    Leetcode1128. 等价多米诺骨牌对的数量
    python 集合和深浅copy
  • 原文地址:https://www.cnblogs.com/overrate-wsj/p/12411960.html
Copyright © 2011-2022 走看看