嘘~ 正在从服务器偷取页面 . . .

洛谷P1083 [NOIP2012 提高组] 借教室 题解


洛谷P1083 [NOIP2012 提高组] 借教室 题解

题目链接:P1083 [NOIP2012 提高组] 借教室

题意

在大学期间,经常需要租借教室。大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室。教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样。

面对海量租借教室的信息,我们自然希望编程解决这个问题。

我们需要处理接下来 \(n\) 天的借教室信息,其中第 \(i\) 天学校有 \(r_i\) 个教室可供租借。共有 \(m\) 份订单,每份订单用三个正整数描述,分别为 \(d_j,s_j,t_j\),表示某租借者需要从第 \(s_j\) 天到第 \(t_j\) 天租借教室(包括第 \(s_j\) 天和第 \(t_j\) 天),每天需要租借 \(d_j\) 个教室。

我们假定,租借者对教室的大小、地点没有要求。即对于每份订单,我们只需要每天提供 \(d_j\) 个教室,而它们具体是哪些教室,每天是否是相同的教室则不用考虑。

借教室的原则是先到先得,也就是说我们要按照订单的先后顺序依次为每份订单分配教室。如果在分配的过程中遇到一份订单无法完全满足,则需要停止教室的分配,通知当前申请人修改订单。这里的无法满足指从第 \(s_j\) 天到第 \(t_j\) 天中有至少一天剩余的教室数量不足 \(d_j\) 个。

现在我们需要知道,是否会有订单无法完全满足。如果有,需要通知哪一个申请人修改订单。

对于 100% 的数据,有\(1 ≤ n,m ≤ 10^6,0 ≤ r_i,d_j≤ 10^9,1 ≤ s_j≤ t_j≤ n\)

考虑差分处理每个需求

然后 \(O(n)\) 扫一遍,如果不合法,就从最后一个人开始消去影响

直到某个人消去以后没问题了,这个人就是罪魁祸首,输出他就好了

为什么倒着消去影响呢?因为罪魁祸首是所有导致不合法的人里面最靠前的

我们只要求这个不合法的人,因此他后面的人不会影响他的坏(感性理解即可

时间复杂度 \(O(n+m)\)

代码:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iomanip>
using namespace std;
namespace FastIO
{
    #define gc() readchar()
    #define pc(a) putchar(a)
    #define SIZ (int)(1e6+15)
    char buf1[SIZ],*p1,*p2;
    char readchar()
    {
        if(p1==p2)p1=buf1,p2=buf1+fread(buf1,1,SIZ,stdin);
        return p1==p2?EOF:*p1++;
    }
    template<typename T>void read(T &k)
    {
        char ch=gc();T x=0,f=1;
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=gc();}
        while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
        k=x*f;
    }
    template<typename T>void write(T k)
    {
        if(k<0){k=-k;pc('-');}
        static T stk[66];T top=0;
        do{stk[top++]=k%10,k/=10;}while(k);
        while(top){pc(stk[--top]+'0');}
    }
}using namespace FastIO;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define N (int)(1e6+15)

int n,m,a[N],b[N],c[N],l[N],r[N];
signed main()
{
    read(n);read(m);
    for(int i=1; i<=n; i++) 
        read(a[i]);
    for(int i=1; i<=m; i++)
    {
        read(c[i]);read(l[i]);read(r[i]);
        b[l[i]]+=c[i];b[r[i]+1]-=c[i];
    }
    int j=m,res=m,sum=0;
    for(int i=1; i<=n; i++)
    {
        sum+=b[i];
        if(sum>a[i])
        {
            while(sum>a[i])
            {
                b[l[j]]-=c[j];
                b[r[j]+1]+=c[j];
                if(l[j]<=i&&i<=r[j])
                    sum-=c[j];
                j--;
            }
            res=j;
        }
    }
    if(res<m)printf("-1\n%lld",res+1);
    else puts("0");
    return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录