poj 3667 hotel (线段树+区间合并)

以前学习过的线段树,在查询和更新的基础上加入了区间合并,利用延迟标志来实现这一方法

代码在这:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int N=50050;

struct node
{
    int l,r;
    int mk;
    int ls,rs,ms;
}tree[N*10];

int n,m;
int x,y,a,b;

void pushup(int i)
{
    int ll=tree[i*2].r-tree[i*2].l+1;
    int rr=tree[i*2+1].r-tree[i*2+1].l+1;
    tree[i].ls=tree[i*2].ls;
    if(tree[i*2].ls==ll) tree[i].ls+=tree[i*2+1].ls;
    tree[i].rs=tree[i*2+1].rs;
    if(tree[i*2+1].rs==rr) tree[i].rs+=tree[i*2].rs;

    tree[i].ms=max(max(tree[i*2].ms,tree[i*2+1].ms),tree[i*2].rs+tree[i*2+1].ls);

}

void buildtree(int i,int l,int r)
{
    tree[i].l=l;
    tree[i].r=r;
    tree[i].mk=-1;
    tree[i].ls=tree[i].rs=tree[i].ms=r-l+1;
    if(l==r) return;
    buildtree(i*2,l,(l+r)/2);
    buildtree(i*2+1,(l+r)/2+1,r);
    pushup(i);
}
void pushdown(int i)
{
    if(tree[i].mk!=-1)
    {
        int ll=tree[i*2].r-tree[i*2].l+1;
        int rr=tree[i*2+1].r-tree[i*2+1].l+1;
        tree[i*2].mk=tree[i*2+1].mk=tree[i].mk;
        tree[i].mk=-1;
        tree[i*2].ls=tree[i*2].rs=tree[i*2].ms=tree[i*2].mk?0:ll;
        tree[i*2+1].ls=tree[i*2+1].rs=tree[i*2+1].ms=tree[i*2+1].mk?0:rr;
    }
}

void updata(int i,int l,int r,int c)
{
    if(tree[i].l==l&&tree[i].r==r)
    {
        tree[i].ms=tree[i].ls=tree[i].rs=c?0:(r-l+1);
        tree[i].mk=c;
        return;
    }
    pushdown(i);
    int m=(tree[i].r+tree[i].l)/2;
    if(r<=m) updata(i*2,l,r,c);
    else if(l>m) updata(i*2+1,l,r,c);
    else
    {
        updata(i*2,l,m,c);
        updata(i*2+1,m+1,r,c);
    }
    pushup(i);
}

int query(int i,int a)
{
    if(tree[i].l==tree[i].r) return tree[i].l;
    pushdown(i);
    int m=(tree[i].r+tree[i].l)/2;
    if(tree[i*2].ms>=a) return query(i*2,a);
    if((tree[i*2].rs+tree[i*2+1].ls)>=a) return m-tree[i*2].rs+1;
    return query(i*2+1,a);
}


int main()
{
    scanf("%d%d",&n,&m);
    buildtree(1,1,n);


    while(m--)
    {
        scanf("%d",&x);
        if(x==1)
        {
            scanf("%d",&y);
            if(tree[1].ms<y) printf("0\n");
            else
            {
                int yy=query(1,y);
                printf("%d\n",yy);
                updata(1,yy,yy+y-1,1);
            }
        }
        else if(x==2)
        {
            scanf("%d%d",&a,&b);
            updata(1,a,a+b-1,0);
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值