【poj 3667】Hotel 题意&&题解&&代码(C++)

63 篇文章 0 订阅

题目链接:
http://poj.org/problem?id=3667
题意:
有n个房间,m个询问,询问的第一个数字若为1,输入一个k,表示寻找一段长度为k的连续空房间,若能找到,则输出满足条件的整段房间里,编号最小的房间的编号,并将这k间空房占满,第一个数字若为2,则输入两个数 x,y,表示将区间x~y的房间全部清空成空房间。
题解:
线段树的每个节点存四个信息:
1 . tr[id].L :表示id所代表的区间中,以最左端开头的最长连续空房间的长度。
2.tr[id].R:表示id所代表的区间中,以最右端结尾的最长连续空房间的长度。
3.tr[id].M:表示id所代表的区间中,最长连续空房间的长度。
4.tr[id].lazy:线段树区间操作时常用信息。。。
具体维护信息的方法与查询方法看代码:
代码:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#define lson (id*2)
#define rson (id*2+1)
using namespace std;
struct node{
    int L;int R;int M;int lazy;
}tr[300005];
void pushup(int id,int l,int r)
{
    int mid=(l+r)/2;
    tr[id].M=max(max(tr[lson].M,tr[rson].M),tr[lson].R+tr[rson].L);
    if (tr[lson].L==mid-l+1)    tr[id].L=tr[lson].L+tr[rson].L;
    else tr[id].L=tr[lson].L;
    if (tr[rson].R==r-mid)      tr[id].R=tr[lson].R+tr[rson].R; 
    else tr[id].R=tr[rson].R;
}
void pushdown(int id,int l,int r)
{
    if (tr[id].lazy!=-1)
    {
        int mid=(l+r)/2;
        tr[lson].R=tr[lson].L=tr[lson].M=tr[id].lazy*(mid-l+1); 
            tr[rson].R=tr[rson].L=tr[rson].M=tr[id].lazy*(r-mid);
        tr[lson].lazy=tr[rson].lazy=tr[id].lazy;
        tr[id].lazy=-1;
    }
}
void build(int id,int l,int r)
{
    tr[id].lazy=-1;
    if (l>r) return ;
    if (l==r) 
    {
        tr[id].L=1;
        tr[id].R=1;
        tr[id].M=1;
        return ;
    }
    int mid=(l+r)/2;
    build(lson,l,mid);
    build(rson,mid+1,r);
    pushup(id,l,r);
}
void exc(int id,int l,int r,int L,int R,int v)
{
    if (l>r || l>R || r<L) return ;
    if (l>=L && r<=R) 
    {
        tr[id].L=v*(r-l+1);
        tr[id].R=v*(r-l+1);
        tr[id].M=v*(r-l+1);
        tr[id].lazy=v;
        return ;
    }
    int mid=(l+r)/2;
    pushdown(id,l,r);
    if (L<=mid) exc(lson,l,mid,L,R,v);
    if (R>=mid+1) exc(rson,mid+1,r,L,R,v);
    pushup(id,l,r);
}
int query(int id,int l,int r,int k)
{
    int mid=(l+r)/2;
    pushdown(id,l,r);
    if (tr[id].M<k) 
    return 0;
    else if (tr[id].L>=k) 
    return l;
    else if (tr[lson].M>=k)
    return query(lson,l,mid,k);
    else    if (tr[lson].R+tr[rson].L>=k)
    return mid-tr[lson].R+1;
    else
    return query(rson,mid+1,r,k);
    return 0;
}
int n,m,p,x,y;
int main()
{
    scanf("%d%d",&n,&m);
    build(1,1,n);
    for (int i=1;i<=m;i++)
    {
        scanf("%d",&p);
        if (p==1)
        {
            scanf("%d",&x);
            int ans=query(1,1,n,x);
            if (ans!=0) exc(1,1,n,ans,ans+x-1,0);
            printf("%d\n",ans);
        }
        else 
        {
            scanf("%d%d",&x,&y);
            exc(1,1,n,x,x+y-1,1);
        }   
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值