• [USACO08FEB] 酒店Hotel


    第一行输入n,m ,n代表有n个房间,编号为1---n,开始都为空房,m表示以下有m行操作,以下 每行先输入一个数 i ,表示一种操作:

    若i为1,表示查询房间,再输入一个数x,表示在1--n 房间中找到长度为x的连续空房,输出连续x个房间中左端的房间号,尽量让这个房间号最小,若找不到长度为x的连续空房,输出0,并且在这x个空房间中住上人。

    若i为2,表示退房,再输入两个数 x,y 代表 房间号 x---x+y-1 退房,即让房间为空。

    Solution

    显然用线段树维护,用类似最大子段和的方法处理

    考虑 update,无非就是更新单侧值,然后再讨论三种情况更新一下 ans

    比较揪心的是如何查询,我们考虑如何在查询时讨论

    • 如果到达递归边界就表明找到,返回

    • 如果左区间足够多就去左区间

    • 否则,如果中间足够多,就直接返回左区间从右开始的最长连续的左端点

    • 否则去右区间找

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 2000005;
    
    int ml[N],mr[N],mx[N],len[N],tag[N];
    
    void build(int p,int l,int r) {
        ml[p]=mr[p]=mx[p]=len[p]=r-l+1;
        if(l<r) {
            build(p*2,l,(l+r)/2);
            build(p*2+1,(l+r)/2+1,r);
        }
    }
    
    void update(int p) {
        if(len[p]==1) return;
        if(mx[p*2]==len[p*2]) ml[p]=len[p*2]+ml[p*2+1];
        else ml[p]=ml[p*2];
        if(mx[p*2+1]==len[p*2+1]) mr[p]=len[p*2+1]+mr[p*2];
        else mr[p]=mr[p*2+1];
        mx[p]=max(max(mx[p*2],mx[p*2+1]),mr[p*2]+ml[p*2+1]);
    }
    
    void pushdown(int p) {
        if(tag[p]==0) return;
        if(tag[p]==1) {
            ml[p*2]=mr[p*2]=mx[p*2]=len[p*2];
            ml[p*2+1]=mr[p*2+1]=mx[p*2+1]=len[p*2+1];
        }
        if(tag[p]==-1) {
            ml[p*2]=mr[p*2]=mx[p*2]=0;
            ml[p*2+1]=mr[p*2+1]=mx[p*2+1]=0;
        }
        tag[p*2]=tag[p*2+1]=tag[p];
        tag[p]=0;
    }
    
    void modify(int p,int l,int r,int ql,int qr,int c) {
        if(l>qr || r<ql) return;
        if(l>=ql&&r<=qr) {
            if(c) ml[p]=mr[p]=mx[p]=len[p], tag[p]=1;
            else ml[p]=mr[p]=mx[p]=0, tag[p]=-1;
        }
        else {
            pushdown(p);
            modify(p*2,l,(l+r)/2,ql,qr,c);
            modify(p*2+1,(l+r)/2+1,r,ql,qr,c);
            update(p);
        }
    }
    
    int query(int p,int l,int r,int ql,int qr,int k) {
        if(l==r) return l;
        pushdown(p);
        if(mx[p*2]>=k) return query(p*2,l,(l+r)/2,ql,qr,k);
        if(mr[p*2]+ml[p*2+1]>=k) return (l+r)/2-mr[p*2]+1;
        return query(p*2+1,(l+r)/2+1,r,ql,qr,k);
    }
    
    int n,m,t1,t2,t3;
    
    int main() {
        scanf("%d%d",&n,&m);
        build(1,1,n);
        for(int i=1;i<=m;i++) {
            scanf("%d",&t1);
            if(t1==1) {
                scanf("%d",&t2);
                if(mx[1]>=t2) {
                    t3=query(1,1,n,1,n,t2);
                    printf("%d
    ",t3);
                    modify(1,1,n,t3,t3+t2-1,0);
                }
                else printf("0
    ");
            }
            else {
                scanf("%d%d",&t2,&t3);
                modify(1,1,n,t2,t2+t3-1,1);
            }
        }
    }
    
  • 相关阅读:
    Ruby on Rails Tutorial笔记
    Gollum安装
    适合新手学习的Rails开源项目
    Rails开发网站流程
    解决Rails找不到Javascript的错误
    工具汇总
    BrowserCMS安装
    Head First Html, CSS, Xhtml
    在80端口运行Rails server
    Ubuntu下安装Balsamiq Mockups
  • 原文地址:https://www.cnblogs.com/mollnn/p/12289796.html
Copyright © 2020-2023  润新知