POJ 3667 Hotel (线段树)

本文介绍了一种使用段式树状数组进行区间更新和查询的算法实现,重点讲解了如何通过递归方式更新和查询左右最长连续个数及区间最大连续个数。文章详细展示了段式树状数组的构建、更新和查询过程,对于理解复杂数据结构和算法有重要价值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

经典题型,注意查询的写法,我跟通常的有所不同,lr表示左右最长连续个数,len为区间最大连续个数。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <string>
#include <vector>
//#include <iostream>
using namespace std;

struct
{
    int l,r,lenth,lazy;
}tree[1000100];

int build(int l,int r,int now)
{

    tree[now].l=r-l+1;
    tree[now].r=r-l+1;
    tree[now].lenth=r-l+1;
    if(l==r)
    {
        return 0;
    }
    build(l,(l+r)/2,now*2);
    build((l+r)/2+1,r,now*2+1);

    return 0;
}

int change(int l,int r,int now,int ll,int rr,int num)
{

    if(tree[now].lazy==1)
    {
        tree[now*2].lazy=1;tree[now*2+1].lazy=1;
        tree[now*2].l=0;tree[now*2+1].l=0;
        tree[now*2].r=0;tree[now*2+1].r=0;
        tree[now*2].lenth=0;tree[now*2+1].lenth=0;
        tree[now].lazy=0;
    }
    else if(tree[now].lazy==2)
    {
        tree[now*2].lazy=2;tree[now*2+1].lazy=2;
        tree[now*2].l=(l+r)/2-l+1;tree[now*2+1].l=(r-(l+r)/2);
        tree[now*2].r=(l+r)/2-l+1;tree[now*2+1].r=(r-(l+r)/2);
        tree[now*2].lenth=(l+r)/2-l+1;tree[now*2+1].lenth=(r-(l+r)/2);
        tree[now].lazy=0;
    }

    if(ll<=l&&rr>=r)
    {
        tree[now].l=num*(r-l+1);
        tree[now].r=num*(r-l+1);
        tree[now].lenth=num*(r-l+1);

        if(num==0) tree[now].lazy=1;
        else tree[now].lazy=2;

        return 0;
    }

    if(rr<=(l+r)/2)
    change(l,(l+r)/2,now*2,ll,rr,num);
    else if(ll>=(l+r)/2+1)
    change((l+r)/2+1,r,now*2+1,ll,rr,num);
    else
    {
        change(l,(l+r)/2,now*2,ll,rr,num);
        change((l+r)/2+1,r,now*2+1,ll,rr,num);
    }


    if(tree[now*2].lenth==((l+r)/2-l+1))
        tree[now].l=tree[now*2].lenth+tree[now*2+1].l;
    else
        tree[now].l=tree[now*2].l;

    if(tree[now*2+1].lenth==(r-(l+r)/2))
        tree[now].r=tree[now*2+1].lenth+tree[now*2].r;
    else
        tree[now].r=tree[now*2+1].r;

    tree[now].lenth=max(tree[now].l,tree[now].r);
    tree[now].lenth=max(tree[now].lenth,tree[now*2].lenth);
    tree[now].lenth=max(tree[now].lenth,tree[now*2+1].lenth);
    tree[now].lenth=max(tree[now].lenth,tree[now*2].r+tree[now*2+1].l);
    return 0;
}

int check(int l,int r,int now,int num,int fuzhu)
{

    if(tree[now].l+fuzhu>=num)
    {
        return l-fuzhu;
    }



    if(tree[now].lazy==1)
    {
        tree[now*2].lazy=1;tree[now*2+1].lazy=1;
        tree[now*2].l=0;tree[now*2+1].l=0;
        tree[now*2].r=0;tree[now*2+1].r=0;
        tree[now*2].lenth=0;tree[now*2+1].lenth=0;

        tree[now].lazy=0;
    }
    else if(tree[now].lazy==2)
    {
        tree[now*2].lazy=2;tree[now*2+1].lazy=2;
        tree[now*2].l=(l+r)/2-l+1;tree[now*2+1].l=(r-(l+r)/2);
        tree[now*2].r=(l+r)/2-l+1;tree[now*2+1].r=(r-(l+r)/2);
        tree[now*2].lenth=(l+r)/2-l+1;tree[now*2+1].lenth=(r-(l+r)/2);

        tree[now].lazy=0;
    }



    int mid=(l+r)/2;
	if(tree[now*2].lenth>=num)
		return check(l,mid,now*2,num,0);
	else
		return check(mid+1,r,now*2+1,num,tree[now*2].r);


}

int main()
{
    int i,j,n,k,m,l,ans;

    while(scanf("%d%d",&n,&m)!=EOF)
    {
        build(1,n,1);

        for(i=0;i<m;i++)
        {
            scanf("%d",&j);

            if(j==1)
            {
                scanf("%d",&j);

                if(tree[1].lenth<j)
                {
                    printf("0\n");

                }
                else
                {
                    ans=check(1,n,1,j,0);
                    printf("%d\n",ans);

                    change(1,n,1,ans,j+ans-1,0);
                }


            }
            else
            {
                scanf("%d%d",&j,&k);

                change(1,n,1,j,j+k-1,1);
            }

        }


    }




    return 0;//
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值