POJ 3667 Hotel 线段树

Description

The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a vacation on the sunny shores of Lake Superior. Bessie, ever the competent travel agent, has named the Bullmoose Hotel on famed Cumberland Street as their vacation residence. This immense hotel has N (1 ≤ N ≤ 50,000) rooms all located on the same side of an extremely long hallway (all the better to see the lake, of course).

The cows and other visitors arrive in groups of size Di (1 ≤ Di ≤ N) and approach the front desk to check in. Each group i requests a set of Di contiguous rooms from Canmuu, the moose staffing the counter. He assigns them some set of consecutive room numbers r..r+Di-1 if they are available or, if no contiguous set of rooms is available, politely suggests alternate lodging. Canmuu always chooses the value of r to be the smallest possible.

Visitors also depart the hotel from groups of contiguous rooms. Checkout i has the parameters Xi and Di which specify the vacating of rooms Xi ..Xi +Di-1 (1 ≤ Xi ≤ N-Di+1). Some (or all) of those rooms might be empty before the checkout.

Your job is to assist Canmuu by processing M (1 ≤ M < 50,000) checkin/checkout requests. The hotel is initially unoccupied.

Input

* Line 1: Two space-separated integers: N and M
* Lines 2..M+1: Line i+1 contains request expressed as one of two possible formats: (a) Two space separated integers representing a check-in request: 1 and D(b) Three space-separated integers representing a check-out: 2, Xi, and Di

Output

* Lines 1.....: For each check-in request, output a single line with a single integer r, the first room in the contiguous sequence of rooms to be occupied. If the request cannot be satisfied, output 0. 


  • 第一次用博客园写blog,应该是我打开姿势不对,怎么感觉对markdown不太友好。
  • 先讲一下题面吧,这道题的大概意思就是有一个有n间房间的房子,m次查询。
  • 如果op=1,那么就找是否有连续的a个房间,如果有,那么返回最边房间的坐标,如果没有就返回0.线段树操作即为成段更新。
  • 如果op=2,那么我们就把区间在[a,a+b-1]内的房间清空。
  • 线段树做法,我们需要维护的值有,当前区间最大值mSum,lSum表示以当某点作为左端点(即起点)开始的连续空房间个数,区间表示即为[l,l+n-1], rSum表示某点作为右端点(即终点)的连续空房间个数,区间表示即为[r-n+1,r]
  • 由于涉及成段更新,自然用到延迟标记,cover数组0为空房间,1为非空。

import java.io.InputStreamReader;
import java.util.Scanner;

public class Main {

    static class _3667{
        static int[] mSum,lSum,rSum; //维护三个值
        static int[] cover; //延迟标记
        static int n,m;

        public void pushDown(int rt,int m){
            if(cover[rt]!=-1){ 
                cover[rt<<1]=cover[rt<<1|1]=cover[rt];
                if(cover[rt]==0){ //若为0 说明没有人
                    mSum[rt<<1]=lSum[rt<<1]=rSum[rt<<1]=m-(m>>1); //设置为当前区间的大小
                    mSum[rt<<1|1]=lSum[rt<<1|1]=rSum[rt<<1|1]=m>>1;
                }else{
                    mSum[rt<<1]=lSum[rt<<1]=rSum[rt<<1]=0; //设置当前区间长度为0 说明已经有人
                    mSum[rt<<1|1]=lSum[rt<<1|1]=rSum[rt<<1|1]=0;
                }
                cover[rt]=-1;
            }
        }

        public void pushUp(int rt,int m){
            lSum[rt]=lSum[rt<<1];
            rSum[rt]=rSum[rt<<1|1];
            if(lSum[rt]==(m-(m>>1))){  
        //说明当前区间是整段覆盖的 这里怎么解释呢 
        //lSum是以l为左端点开始的连续房间数,
        //若房间数等于整个房间大小说明lSum[rt<<1]的长为[l,l+mid],
        //那么lSum的长度可以扩展到以mid+1为左端点这一段区间。
        //最终长度为[l,....,mid,mid+1,,,pos(连续空房间的终点)]
         lSum[rt]+=lSum[rt<<1|1];
            }
            if(rSum[rt]==(m>>1)){
          //同理 以r为右边端点 rSum[rt<<1|1]的长为[mid+1,r],
          //那么rSum的长度可以拓展到以mid为右端点这一段区间。
          //[pos(连续空房间的起点),....,mid,mid+1,...,r]
                rSum[rt]+=rSum[rt<<1];
            }
            mSum[rt]=Math.max(lSum[rt<<1|1]+rSum[rt<<1],Math.max(mSum[rt<<1],mSum[rt<<1|1]));
       // 为啥要比较lSum[rt<<1|1]+rSum[rt<<1]
       //应该懂了8,即[pos[st],..,mid,mid+1,..,pos[ed]] 中间段
        }

        public void build(int l,int r,int rt){ //建树
            mSum[rt]=lSum[rt]=rSum[rt]=r-l+1; //值为区间的宽度
            cover[rt]=-1;
            if(l==r){
                return;
            }
            int mid=(l+r)>>1;
            build(l,mid,rt<<1);
            build(mid+1,r,rt<<1|1);
        }

        public int query(int p,int l,int r,int rt){ //查询
            if(l==r){
                return l;
            }
            pushDown(rt,r-l+1);
            int mid=(l+r)>>1;
            if(mSum[rt<<1]>=p){ //优先左边区间
                return query(p,l,mid,rt<<1);
            }else if(lSum[rt<<1|1]+rSum[rt<<1]>=p){ //中间区间
                return mid-rSum[rt<<1]+1;
            }
            return query(p,mid+1,r,rt<<1|1); //右边区间
        }

        public void update(int p,int L,int R,int l,int r,int rt){ //这个就不说了
            if(L<=l&&r<=R){
                cover[rt]=p;
                if(p==0){
                    mSum[rt]=lSum[rt]=rSum[rt]=r-l+1;
                }else{
                    mSum[rt]=lSum[rt]=rSum[rt]=0;
                }
                return;
            }
            pushDown(rt,r-l+1);
            int mid=(l+r)>>1;
            if(L<=mid){
                update(p,L,R,l,mid,rt<<1);
            }
            if(R>mid){
                update(p,L,R,mid+1,r,rt<<1|1);
            }
            pushUp(rt,r-l+1);
        }

        public void run() {
            Scanner cin=new Scanner(new InputStreamReader(System.in));
            n=cin.nextInt();
            m=cin.nextInt();
            mSum=new int[n<<2];
            lSum=new int[n<<2];
            rSum=new int[n<<2];
            cover=new int[n<<2];
            build(1,n,1);
            for(int i=0;i<m;++i){
                int op=cin.nextInt();
                if(op==1){
                    int c=cin.nextInt();
                    if(mSum[1]<c){
                        System.out.println("0");
                    }else{
                        int idx=query(c,1,n,1);
                        System.out.println(idx);
                        update(1,idx,idx+c-1,1,n,1);
                    }
                }else{
                    int a=cin.nextInt();
                    int b=cin.nextInt();
                    update(0,a,a+b-1,1,n,1);
                }
            }
        }
    }

    public static void main(String[] args) {
        _3667 main=new _3667();
        main.run();
    }

}

  

  

 

猜你喜欢

转载自www.cnblogs.com/viscu/p/9727320.html