• Luogu 1083 借教室(二分,差分)


    Luogu 1083 借教室(二分,差分)

    Description

    在大学期间,经常需要租借教室。大到院系举办活动,小到学习小组自习讨论,都需要 向学校申请借教室。教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样。
    面对海量租借教室的信息,我们自然希望编程解决这个问题。
    我们需要处理接下来n天的借教室信息,其中第i天学校有ri个教室可供租借。共有m份 订单,每份订单用三个正整数描述,分别为dj,sj,tj,表示某租借者需要从第sj天到第tj天租 借教室(包括第sj天和第tj天),每天需要租借dj个教室。
    我们假定,租借者对教室的大小、地点没有要求。即对于每份订单,我们只需要每天提 供dj个教室,而它们具体是哪些教室,每天是否是相同的教室则不用考虑。
    借教室的原则是先到先得,也就是说我们要按照订单的先后顺序依次为每份订单分配教 室。如果在分配的过程中遇到一份订单无法完全满足,则需要停止教室的分配,通知当前申 请人修改订单。这里的无法满足指从第sj天到第tj天中有至少一天剩余的教室数量不足dj个。
    现在我们需要知道,是否会有订单无法完全满足。如果有,需要通知哪一个申请人修改 订单。

    Input

    第一行包含两个正整数n,m,表示天数和订单的数量。
    第二行包含n个正整数,其中第i个数为ri,表示第i天可用于租借的教室数量。
    接下来有m行,每行包含三个正整数dj,sj,tj,表示租借的数量,租借开始、结束分别在 第几天。
    每行相邻的两个数之间均用一个空格隔开。天数与订单均用从1开始的整数编号。

    Output

    如果所有订单均可满足,则输出只有一行,包含一个整数 0。否则(订单无法完全满足) 输出两行,第一行输出一个负整数-1,第二行输出需要修改订单的申请人编号。

    Sample Input

    4 3
    2 5 4 3
    2 1 3
    3 2 4
    4 2 4

    Sample Output

    -1
    2

    Http

    Luogu:https://www.luogu.org/problem/show?pid=1083

    Source

    二分,差分

    题目大意

    若干天中,每天有一些教室空出。现在给出若干订单,每一个订单都是要一段连续天数的固定数量教室。现在求到第几个订单会不满足要求

    解决思路

    因为如果有一个订单不满足要求,会导致后面的订单都不满足要求,这个符合单调性原理。所以我们可以二分满足到第几个订单。而对于每一次检查从1~mid的订单,我们用差分来处理,将订单的第一天加上要借的教室数,最后一天的后一天减去要借的教室数。然后从前往后累加一遍,如果出现任意一天不满足情况时,记录答案。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int maxN=2000000;
    const int inf=2147483647;
    
    #define ll long long
    
    int n,m;
    int Ans;
    int Op[maxN];//订单开始的时间
    int Ed[maxN];//订单结束的时间
    int Num[maxN];//订单要借的教室数
    ll Sum[maxN];//统计差分
    int Classroom[maxN];//每一天能够借出的教室数
    
    int read();
    bool check(int end);
    
    int main()
    {
        n=read();
        m=read();
        Ans=inf;
        for (int i=1;i<=n;i++)
            Classroom[i]=read();
        for (int i=1;i<=m;i++)
        {
            Num[i]=read();
            Op[i]=read();
            Ed[i]=read();
        }
        if (check(m))//当最后一个订单都可以满足时,直接输出可以并退出
        {
            printf("0
    ");
            return 0;
        }
        int l=1,r=m;//二分
        do
        {
            int mid=(l+r)/2;
            if (check(mid))//检查可行性,若可以满足则上调左指针,否则下调右指针
                l=mid+1;
            else
                r=mid;
        }
        while (l<r);
        printf("-1
    %d
    ",Ans);
        return 0;
    }
    
    int read()
    {
        int x=0;
        char ch=getchar();
        while ((ch>'9')||(ch<'0'))
            ch=getchar();
        while ((ch<='9')&&(ch>='0'))
        {
            x=x*10+ch-48;
            ch=getchar();
        }
        return x;
    }
    
    bool check(int end)
    {
        memset(Sum,0,sizeof(Sum));
        for (int i=1;i<=end;i++)//记录差分
        {
            Sum[Op[i]]+=1LL*Num[i];//第一天
            Sum[Ed[i]+1]-=1LL*Num[i];//最后一天的后一天
        }
        ll now=0;
        for (int i=1;i<=n;i++)//累计前缀和
        {
            now+=Sum[i];
            if (now>Classroom[i])//当只要出现一个不满足
            {
                Ans=min(Ans,end);//记录答案并返回
                return 0;
            }
        }
        return 1;
    }
    
  • 相关阅读:
    linux 进程等待 wait 、 waitpid
    数理逻辑量词的引入
    Android自己定义动态布局 — 多图片上传
    Dynamics CRM 2015/2016 Web API:Unbound Custom Action 和 Bound Custom Action
    iOS 9应用开发教程之显示编辑文本标签文本框
    iOS 9应用开发教程之ios9中实现按钮的响应
    iOS 9应用开发教程之使用代码添加按钮美化按钮
    iOS 9应用开发教程之ios9的视图
    iOS 9应用开发教程之定制应用程序图标以及真机测试
    iOS 9应用开发教程之编辑界面与编写代码
  • 原文地址:https://www.cnblogs.com/SYCstudio/p/7604110.html
Copyright © 2020-2023  润新知