• P1083 [NOIP2012 提高组] 借教室


     

    不要把天数看成一个动态的时间,用数组存储某天原本有多少个教室,表示为第i天原有s[i]个教室.

    很容易看出来问题有单调性,所以二分订单数求解.

    对于每份订单,其将会使第a天到第b天的教室数量均减少c个.故构造一个差分数组sum,使得sum的前缀和表示对应某天教室数量的变化量.则当天剩余的教室数量为s[i]+(sum[i]的前缀和).

    一旦发现某天剩余教室数量小于0,说明不符合,可以很容易写出check函数.

    注意如果所有的check都返回了真,最后会有l==m+1,即r保持初始值未变且l增长到r.

    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    int n, m, s[1000010];
    int sum[1000010];
    struct S {
        int d, s, t;
    } a[1000010];
    
    bool check(int x) {
        memset(sum, 0, sizeof(int) * (n + 1));
        for (int i = 1; i <= x; i++) {
            sum[a[i].s] -= a[i].d;
            sum[a[i].t + 1] += a[i].d;
        }
        for (int i = 1; i <= n; i++) {
            sum[i] += sum[i - 1];
            if (sum[i] + s[i] < 0) return false;
        }
        return true;
    }
    
    int main() {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) scanf("%d", s + i);
        for (int i = 1; i <= m; i++) scanf("%d%d%d", &a[i].d, &a[i].s, &a[i].t);
    
        int l = 0, r = m + 1;
        while (l < r) {
            int mid = l + r + 1 >> 1;
            if (check(mid))
                l = mid;
            else
                r = mid - 1;
        }
    
        if (l == m + 1)
            puts("0");
        else
            printf("-1
    %d
    ", l + 1);
    
        return 0;
    }
    P1083
  • 相关阅读:
    C和C++内存模型
    makefile 学习归纳
    为知笔记给你更多
    二级指针探讨
    使用vscode书写博客
    C/C++ 笔试题一
    从一段经典错误代码说起——关于局部变量指针和函数传参的问题分析
    socket编程再分析(-)——基础
    samba服务器配置
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />详解
  • 原文地址:https://www.cnblogs.com/Gaomez/p/14258933.html
Copyright © 2020-2023  润新知