• POJ 3667 Hotel【经典的线段树】


    POJ 3667 Hotel

    http://poj.org/problem?id=3667
    题目大意:
        奶牛们最近的旅游计划,是到苏必利尔湖畔,享受那里的湖光山色,以及
    明媚的阳光。作为整个旅游的策划者和负责人,贝茜选择在湖边的一家著名的
    旅馆住宿。这个巨大的旅馆一共有N (1 <= N <= 50,000)间客房,它们在同一层
    楼中顺次一字排开,在任何一个房间里,只需要拉开窗帘,就能见到波光粼粼的
    湖面。

        贝茜一行,以及其他慕名而来的旅游者,都是一批批地来到旅馆的服务台,
    希望能订到D_i (1 <= D_i <= N)间连续的房间。服务台的接待工作也很简单:
    如果存在r满足编号为r..r+D_i-1的房间均空着,他就将这一批顾客安排到这些
    房间入住;如果没有满足条件的r,他会道歉说没有足够的空房间,请顾客们另
    找一家宾馆。如果有多个满足条件的r,服务员会选择其中最小的一个。

        旅馆中的退房服务也是批量进行的。每一个退房请求由2个数字X_i、D_i
    描述,表示编号为X_i..X_i+D_i-1 (1 <= X_i <= N-D_i+1)房间中的客人全部
    离开。退房前,请求退掉的房间中的一些,甚至是所有,可能本来就无人入住。

        而你的工作,就是写一个程序,帮服务员为旅客安排房间。你的程序一共
    需要处理M (1 <= M < 50,000)个按输入次序到来的住店或退房的请求。第一个
    请求到来前,旅店中所有房间都是空闲的。

    分析:
    线段树,节点内存入左连续块,右连续块,以及当前区间内的最大连续块
    将订房服务分为两步:
    1.查询是否存在d连续块,若存在,返回r
    2.根据1,进行实际的住房操作,即将[r,r+d-1]区间住满
    退房服务,与2类似

    View Code
    #include<stdio.h>
    const int N = 50000+10;
    /*节点*/
    struct node
    {
    int left,right;
    int cval;//该区间内最大的连续块长度
    int lval,rval;//左、右边界连续块得长度
    };
    node tree[N
    *3];

    //将id所对应的区间置满或置空
    inline void initNode(int id,int state)
    {
    int len = tree[id].right - tree[id].left+1;
    tree[id].cval
    = state*len;
    tree[id].lval
    = tree[id].cval;
    tree[id].rval
    = tree[id].cval;
    }

    inline
    int max(int a,int b)
    {
    return a>b?a:b;
    }

    //获得id所在区间的长度
    inline int getLen(int id)
    {
    return tree[id].right-tree[id].left+1;
    }

    //建树
    void createTree(int left,int right,int id)
    {
    tree[id].left
    =left;
    tree[id].right
    = right;
    initNode(id,
    1);
    if(tree[id].left == tree[id].right)return;

    int mid = (left+right)>>1;
    createTree(left,mid,
    2*id);
    createTree(mid
    +1,right,2*id+1);
    }

    //查询是否存在长度为need的连续段,若存在返回其左端所在位置
    int search(int need,int id)
    {
    if(tree[id].cval<need)return 0;
    if(tree[id].left==tree[id].right)return tree[id].left;
    if(tree[id].lval>=need)return tree[id].left;

    if(tree[2*id].cval>=need)
    return search(need,2*id);
    else
    if(tree[2*id].rval+tree[2*id+1].lval>=need)
    return tree[2*id].right-tree[2*id].rval+1;
    else
    return search(need,2*id+1);
    }

    /*更新left,right区间,将其置空或置满*/
    void update(int left,int right,int id,int state)
    {
    int len = tree[id].right - tree[id].left+1;
    if(tree[id].left>=left&&tree[id].right<=right)
    {
    initNode(id,state);
    return;
    }

    int mid = (tree[id].left+tree[id].right)>>1;

    if(tree[id].cval == len || tree[id].cval == 0)
    {
    int st = 0;
    if(tree[id].cval!=0)st = 1;
    initNode(
    2*id,st);
    initNode(
    2*id+1,st);
    }

    if(right<=mid)
    update(left,right,
    2*id,state);
    else
    if(left>mid)
    update(left,right,
    2*id+1,state);
    else
    {
    update(left,mid,
    2*id,state);
    update(mid
    +1,right,2*id+1,state);
    }

    tree[id].lval
    = tree[2*id].lval;
    if(tree[id].lval==getLen(2*id))
    tree[id].lval
    +=tree[2*id+1].lval;
    tree[id].rval
    = tree[2*id+1].rval;
    if(tree[id].rval== getLen(2*id+1))
    tree[id].rval
    +=tree[2*id].rval;
    tree[id].cval
    = tree[2*id].rval+tree[2*id+1].lval;
    tree[id].cval
    = max(tree[2*id].cval,tree[id].cval);
    tree[id].cval
    = max(tree[2*id+1].cval,tree[id].cval);

    }

    int main()
    {
    int n,m;
    scanf(
    "%d%d",&n,&m);
    createTree(
    1,n,1);
    int f,d,x;
    while(m--)
    {
    scanf(
    "%d",&f);
    if(f==1)
    {
    scanf(
    "%d",&d);
    int r = search(d,1);
    printf(
    "%d\n",r);
    if(r)
    {
    update(r,r
    +d-1,1,0);//放满
    }
    }
    else
    {
    scanf(
    "%d%d",&x,&d);
    update(x,x
    +d-1,1,1);
    }
    }
    return 0;
    }
  • 相关阅读:
    自定义predicate来对List进行去重
    ParameterizedType
    万级TPS亿级流水-中台账户系统架构设计
    【Linux】【压测】基于python Locust库实现自动化压测实践
    家里宽带ADSL是城域网IP以及公网IP的具体区别和联系
    fiddler如何使用Xposed+JustTrustMe来突破SSL Pinning
    幽门螺旋杆菌检查方法那么多,到底选择哪个?
    apache (httpd)不支持中文路径问题
    皮肤瘙痒症、干燥瘙痒、荨麻疹和丘疹性荨麻疹区别和联系
    Redmi K30和Redmi K30 5G和Redmi K30 5G极速版和Redmi K30i 5G
  • 原文地址:https://www.cnblogs.com/AndreMouche/p/1982135.html
Copyright © 2020-2023  润新知