luogu P1083 借教室

本文详细解析了借教室问题的算法实现,采用二分查找、前缀和及贪心策略,通过实例演示如何确定最优的教室借用方案,并确保不超过可用教室数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二次联通门 : luogu P1083 借教室

 

 

 

/*    
    luogu P1083 借教室 
    
    
    二分 + 前缀和 + 贪心 
    
    其实一看这个题我是想用线段树去做的....
    根本看不出从哪里要二分..
    
    思路:
        二分一下订单的编号
        检查答案是否可行, 可行就向后找 , 否则就向前找..
        
        前缀和是第 i 天需要的教室数 
        具体检查过程   做一下前缀和
            比如 l~r 天要x个教室
            那么 sum[l] += x
                 sum[r + 1] -= x
                这样的话就处理出了第i天要借的教室数
                最后加起来看看是否超过原有的教室即可 
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#define Max 1000209

using namespace std;

void read (int &now)
{
    now = 0;
    char word = getchar ();
    while (word < '0' || word > '9')
        word = getchar ();
    while (word >= '0' && word <= '9')
    {
        now = now * 10 + word - '0';
        word = getchar ();
    }
}
int N;
int M;
int sum[Max];
int number[Max];
int Answer;
struct Ruri
{
    int number;
    int start;
    int end;
}res[Max];
bool Check (int day)
{
    memset (sum, 0, sizeof (sum));
    int now = 0;
    for (int i = 1; i <= day; i++)
    {
        sum[res[i].start] += res[i].number;
        sum[res[i].end + 1] -= res[i].number;
    }
    for (int i = 1; i <= N; i++)
    {
        now += sum[i];
        if (now > number[i])
            return false;
    }
    return true;
}
int main (int argc, char *argv[])
{
    read (N);
    read (M);
    for (int i = 1; i <= N; i++)
        read (number[i]);
    for (int i = 1; i <= M; i++)
    {
        read (res[i].number);
        read (res[i].start);
        read (res[i].end);
    }
    int l = 1;
    int r = M;
    int Mid;
    while (l <= r)
    {
        Mid = (l + r) >> 1;
        if (Check (Mid))
            l = Mid + 1;
        else 
        {
            Answer = Mid;
            r = Mid - 1;
        }
    }
    if (!Answer)
        putchar ('0');
    else 
        printf ("-1\n%d", Answer);
    return 0;
}

 

转载于:https://www.cnblogs.com/ZlycerQan/p/6883150.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值