旅馆 Hotel

Description

奶牛们最近的旅游计划,是到苏必利尔湖畔,享受那里的湖光山色,以及明媚的阳光。作为整个旅游的策划者和负责人,贝茜选择在湖边的一家著名的旅馆住宿。这个巨大的旅馆一共有N (1 <= N <= 50,000)间客房,它们在同一层楼中顺次一字排开,在任何一个房间里,只需要拉开窗帘,就能见到波光粼粼的湖面。
贝茜一行,以及其他慕名而来的旅游者,都是一批批地来到旅馆的服务台,希望能订到Di (1 <= Di <= N)间连续的房间。
服务台的接待工作也很简单:如果存在r满足编号为r..r+Di-1的房间均空着,他就将这一批顾客安排到这些房间入住;如果没有满足条件的r,他会道歉说没有足够的空房间,请顾客们另找一家宾馆。如果有多个满足条件的r,服务员会选择其中最小的一个。
旅馆中的退房服务也是批量进行的。每一个退房请求由2个数字Xi、Di 描述,表示编号为Xi..Xi+Di-1 (1 <= Xi <= N-Di+1)房间中的客人全部离开。退房前,请求退掉的房间中的一些,甚至是所有,可能本来就无人入住。
而你的工作,就是写一个程序,帮服务员为旅客安排房间。你的程序一共需要处理M (1 <= M < 50,000)个按输入次序到来的住店或退房的请求。第一个请求到来前,旅店中所有房间都是空闲的。

Input

 第1行: 2个用空格隔开的整数:N、M
* 第2..M+1行: 第i+1描述了第i个请求,如果它是一个订房请求,则用2个数字 1、Di描述,数字间用空格隔开;如果它是一个退房请求,用3 个以空格隔开的数字2、Xi、Di描述

Output

第1..m行: 对于每个订房请求,输出1个独占1行的数字:如果请求能被满足 ,输出满足条件的最小的r;如果请求无法被满足,输出0

Sample Input

10 6
1 3
1 3
1 3
1 3
2 5 5
1 6

Sample Output

1
4
7
0
5

#include <bits/stdc++.h>

using namespace std;

struct tree{
    int lazy;
	int sum;
	int lmax;
	int rmax;
	int mmax;
}tree[5000001];

int n, m;

void pushup( int p )
{
    tree[p].sum = max( max( tree[p<<1].sum, tree[p<<1|1].sum ), tree[p<<1|1].lmax + tree[p<<1].rmax );
    tree[p].lmax = tree[p<<1].lmax;
    
    if( tree[p<<1].sum == tree[p<<1].mmax )
	{
		tree[p].lmax = tree[p<<1].sum + tree[p<<1|1].lmax;
	}
	
    tree[p].rmax = tree[p<<1|1].rmax;
    
    if( tree[p<<1|1].sum == tree[p<<1|1].mmax )
	{
		tree[p].rmax = tree[p<<1|1].sum + tree[p<<1].rmax;
	}
}

void build( int p, int l, int r )
{
    tree[p].lazy = -1;
    tree[p].lmax = tree[p].rmax = tree[p].sum = tree[p].mmax = r - l + 1;
    
    if( l == r )
	{
		return ;
	}
	
    int mid = ( l + r ) >> 1;
    
    build( p<< 1, l, mid );
    build( p<< 1 | 1, mid + 1, r );
    pushup(p);
}

void pushdown( int p )
{
    if( tree[p].lazy == 1 )
	{
        tree[p<<1].lmax = tree[p<<1].rmax = tree[p<<1].sum = tree[p<<1].mmax;
        tree[p<<1|1].lmax = tree[p<<1|1].rmax = tree[p<<1|1].sum = tree[p<<1|1].mmax;
        tree[p<<1].lazy = tree[p<<1|1].lazy = 1;
    }
    if( tree[p].lazy == 0 )
	{
        tree[p<<1].lmax = tree[p<<1].rmax = tree[p<<1].sum = 0;
        tree[p<<1|1].lmax = tree[p<<1|1].rmax = tree[p<<1|1].sum = 0;
        tree[p<<1].lazy = tree[p<<1|1].lazy = 0;
    }
    
    tree[p].lazy = -1;
}

void update( int p, int l, int r, int L, int R, int x )
{
    if( l >= L && r <= R )
	{
        tree[p].lmax = tree[p].rmax = tree[p].sum = tree[p].mmax*x;
        tree[p].lazy = x;
        return;
    }
    
    pushdown(p);
    
	int mid = ( l + r ) >> 1;
	
    if( L <= mid )
	{
		update( p << 1, l, mid, L, R, x );
	}
    if( R > mid )
	{
    	update( p << 1 | 1, mid + 1, r, L, R, x );
	}
	
    pushup(p);
}

int query( int p, int l, int r, int x )
{
    pushdown(p);
    
    int mid = ( l + r ) >> 1;
    
	if( l == r )
	{
		return l;
	}
	
    if( tree[p<<1].sum >= x )
	{
		return query( p << 1, l, mid, x );
	}
    else if( tree[p<<1].rmax + tree[p<<1|1].lmax >= x )
	{
		return mid - tree[p<<1].rmax + 1;
	}
	else
	{
		return query( p << 1 | 1, mid + 1, r, x );
	}
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    
	cin >> n >> m;
    
	build( 1, 1, n );
    
    for( int i = 1; i <= m; i++ )
	{
        int op, x;
        
        cin >> op >> x;
        
		if( op == 1 )
		{
            if( tree[1].sum < x )
			{
                cout << "0" << '\n';
                continue;
            }
            
            int man = query( 1, 1, n, x );
            
			cout << man << '\n';
			
            update( 1, 1, n, man, man + x - 1, 0 );
        }
        else if(op==2){
            int y;
            cin >> y;
            update(1,1,n,x,x+y-1,1);
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值