poj 3667 Hotel 线段树+区间合并

#include<cstdio>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ls rt<<1
#define rs ls|1
const int maxn=50010;
int sumL[maxn<<2],sumR[maxn<<2],sumM[maxn<<2],col[maxn<<2];
void up(int l,int r,int rt)
{
    int m=(r-l+1);
    sumL[rt]=sumL[ls];
    sumR[rt]=sumR[rs];
    if(sumL[ls]==m-m/2)sumL[rt]+=sumL[rs];
    if(sumR[rs]==m/2)sumR[rt]+=sumR[ls];
    sumM[rt]=max(sumL[rs]+sumR[ls],max(sumM[ls],sumM[rs]));
}
void down(int l,int r,int rt)
{
    int m=(r-l+1);
    if(col[rt]!=-1)
    {
        sumL[ls]=sumR[ls]=sumM[ls]=col[rt]?m-m/2:0;
        sumL[rs]=sumR[rs]=sumM[rs]=col[rt]?m/2:0;
        col[ls]=col[rs]=col[rt];
        col[rt]=-1;
    }
}
void build(int l,int r,int rt)
{
    col[rt]=-1;
    sumR[rt]=sumL[rt]=sumM[rt]=r-l+1;
    if(l==r)return;
    int m=(l+r)/2;
    build(lson);
    build(rson);
}
void update(int L,int R,int key,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        col[rt]=key;
        sumL[rt]=sumR[rt]=sumM[rt]=col[rt]?r-l+1:0;
        return;
    }
    down(l,r,rt);
    int m=(l+r)/2;
    if(L<=m)update(L,R,key,lson);
    if(m<R)update(L,R,key,rson);
    up(l,r,rt);
}
int query(int tol,int l,int r,int rt)
{
    if(l==r)return l;
    down(l,r,rt);
    int m=(l+r)/2;
    if(sumM[ls]>=tol)return query(tol,lson);
    else
    if(sumL[rs]+sumR[ls]>=tol)return m-sumR[ls]+1;
    else
    return query(tol,rson);
}
int main()
{
    int n,m,op,tol,L,R,d;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        build(1,n,1);
        while(m--)
        {
            scanf("%d",&op);
            if(op==1)
            {
                scanf("%d",&tol);
                if(sumM[1]<tol)
                {
                    printf("0\n");
                    continue;
                }
                L=query(tol,1,n,1);
                printf("%d\n",L);
                R=L+tol-1;
                update(L,R,0,1,n,1);
            }
            else
            {
                scanf("%d%d",&L,&d);
                R=L+d-1;
                update(L,R,1,1,n,1);
            }
        }
    }
}
View Code

 

转载于:https://www.cnblogs.com/Hungry3/p/3426005.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值