• Hotel 旅馆, 线段树查询,合并


    C. Hotel 旅馆

    内存限制:256 MiB 时间限制:1000 ms 标准输入输出
    题目类型:传统 评测方式:文本比较
     

    题目描述

    OIER最近的旅游计划,是到长春净月潭,享受那里的湖光山色,以及明媚的阳光。作为整个旅游的策划者和负责人,贝茜选择在湖边的一家著名的旅馆住宿。这个巨大的旅馆一共有N

    间客房,它们在同一层楼中顺次一字排开,在任何一个房间里,只需要拉开窗帘,就能见到波光粼粼的湖面。 所有的旅游者,都是一批批地来到旅馆的服务台,希望能订到 间连续的房间。服务台的接待工作也很简单:如果存在r满足编号为 的房间均空着,他就将这一批顾客安排到这些房间入住;如果没有满足条件的r,他会道歉说没有足够的空房间,请顾客们另找一家宾馆。如果有多个满足条件的r,服务员会选择其中最小的一个。 旅馆中的退房服务也是批量进行的。每一个退房请求由2个数字 、 描述,表示编号为 房间中的客人全部离开。退房前,请求退掉的房间中的一些,甚至是所有,可能本来就无人入住。 而你的工作,就是写一个程序,帮服务员为旅客安排房间。你的程序一共需要处理

    个按输入次序到来的住店或退房的请求。第一个请求到来前,旅店中所有房间都是空闲的。

    输入格式

    第1行: 2个用空格隔开的整数:N、M

    第2..M+1行: 第i+1描述了第i个请求,如果它是一个订房请求,则用2个数字 1、

    描述,数字间用空格隔开;如果它是一个退房请求,用3 个以空格隔开的数字

    、 、 描述

    输出格式

    第1..??行: 对于每个订房请求,输出1个独占1行的数字:如果请求能被满足 ,输出满足条件的最小的r;如果请求无法被满足,输出0

    样例

    样例输入

    10 6
    1 3
    1 3
    1 3
    1 3
    2 5 5
    1 6
    
    

    样例输出

    1
    4
    7
    0
    5
    

    线段树区间合并裸题 我们设这样几个数组 : max_near、max_l、max_r、lazy来分别表示区间最大连续长度,从左开始的最大连续长度,从右开始的区间最大连续长度、懒度标记 
     
    这样 我们的max_near就是max(max(max_near[lc],max_near[rc]),max_r[lc]+max_r[lc]) 对于max_l的维护,若左儿子的max_next等于len,那么就是左儿子的len加右儿子max_l,否则是左儿子的max_l,max_r类似。
     
    对于每次查询,如果max_near[root] < query ,那么直接输出0即可,否则的话以 左子树? 左子树右加右子树左 ? 右子树的顺序选择递归,返回ans并从ans+query的区间范围对树进行修改


    代码:
    #include<bits/stdc++.h>
    #define re register int
    using namespace std;
    int n,m,o;
    int a,d,x,maxx;
    int max_near[500100],max_l[500100],max_r[500100],len[500100],lazy[500100],cl[500100],cr[500100];
    void pp(int k)
    {
        max_l[k]=max_l[k<<1];
        max_r[k]=max_r[k<<1|1];
        if(max_l[k]==(cr[k<<1]-cl[k<<1]+1))
            max_l[k]+=max_l[k<<1|1];
        if(max_r[k]==(cr[k<<1|1]-cl[k<<1|1]+1))
            max_r[k]+=max_r[k<<1];
        max_near[k]=max(max_r[k<<1]+max_l[k<<1|1],max(max_near[k<<1],max_near[k<<1|1]));
        
        /*
            错误搞法
        len[k]=len[k<<1]+len[k<<1|1];
        
        max_l[k]=(max_near[k<<1]==len[k<<1])?(len[k<<1]+max_l[k<<1|1]):max_l[k<<1];
        
        max_r[k]=(max_near[k<<1|1]==len[k<<1|1])?(len[k<<1|1]+max_r[k<<1]):max_r[k<<1|1];
        max_near[k]=max_r[k<<1]+max_l[k<<1|1];
        
        */
        return;
    }
    void build(int k,int l,int r)
    {
        cl[k]=l;
        cr[k]=r;
        lazy[k]=-1;
        if(l==r)
        {
            max_l[k]=max_r[k]=max_near[k]=len[k]=1;
            return;
        }
        int m=(l+r)>>1;
        build(k<<1,l,m);
        build(k<<1|1,m+1,r);
        pp(k);
    }
    void pushdown(int r,int lc,int rc)
    {
        if(lazy[r]!=-1)
        {
            lazy[lc]=lazy[rc]=lazy[r];
            if(lazy[r])
            {
                max_near[lc]=max_l[lc]=max_r[lc]=len[lc]=0;
                max_near[rc]=max_l[rc]=max_r[rc]=len[rc]=0;
            }
            else
            {
                max_near[lc]=max_l[lc]=max_r[lc]=len[lc]=cr[lc]-cl[lc]+1;
                max_near[rc]=max_l[rc]=max_r[rc]=len[rc]=cr[rc]-cl[rc]+1;
            }
            lazy[r]=-1;
        }
    }
    int que(int k,int d)
    {
        int m=(cl[k]+cr[k])>>1;
        if(cl[k]==cr[k])
            return cl[k];
        /*    
            错误,因为开端不一定在最左边!
            if(max_near[k]==d)
            return cl[k];
        */
        pushdown(k,k<<1,k<<1|1);
        if(max_near[k<<1]>=d)
            return    que(k<<1,d);
         if(max_r[k<<1]+max_l[k<<1|1]>=d)  
            return m-max_r[k<<1]+1;
        else
            return que(k<<1|1,d);
    }

    void updata(int l,int r,int root,int z)
    {
        if(l<=cl[root]&&cr[root]<=r)
        {
            lazy[root]=z;
            if(z)
                max_near[root]=max_l[root]=max_r[root]=len[root]=0;
            else
                max_near[root]=max_l[root]=max_r[root]=len[root]=cr[root]-cl[root]+1;
            return;
        }
        int m=(cr[root]+cl[root])>>1;
        pushdown(root,root<<1,root<<1|1);
        if(m>=l)
            updata(l,r,root<<1,z);
        if(m<r)
            updata(l,r,root<<1|1,z);
        pp(root);
    }
    int qian(int x)
    {
        if(cl[x<<1])
            qian(x<<1);
        if(cl[x<<1|1])
            qian(x<<1|1);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        build(1,1,n);
        for(re i=1;i<=m;i++)
        {
            scanf("%d",&a);
            if(a==1)
            {
                scanf("%d",&d);
                if(max_near[1]<d)
                {
                    printf("0\n");
                    continue;
                }
                o=que(1,d);
                printf("%d\n",o);
                updata(o,o+d-1,1,1);
            }
            else
            {
                scanf("%d%d",&x,&d);
                updata(x,x+d-1,1,0);
            }
        }
        return 0;
    }

  • 相关阅读:
    Redis学习
    extractor
    Linux fork exec等
    Linux kill 命令
    GCC参数使用
    Shell 参数(2) --解析命令行参数工具:getopts/getopt
    Shell 参数(1)
    shell 中并发执行
    Linux 下新增用户的流程
    Linux 安全rm
  • 原文地址:https://www.cnblogs.com/WindZR/p/14600837.html
Copyright © 2020-2023  润新知