题意:
链接:https://ac.nowcoder.com/acm/contest/22353/H
来源:牛客网
题干:
在大学期间,经常需要租借教室。大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室。教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样。
面对海量租借教室的信息,我们自然希望编程解决这个问题。
我们需要处理接下来n天的借教室信息,其中第i天学校有ri个教室可供租借。共有m份订单,每份订单用三个正整数描述,分别为dj, sj, tj,表示某租借者需要从第sj天到第tj天租借教室(包括第sj天和第tj天),每天需要租借dj个教室。
我们假定,租借者对教室的大小、地点没有要求。即对于每份订单,我们只需要每天提供dj个教室,而它们具体是哪些教室,每天是否是相同的教室则不用考虑。
借教室的原则是先到先得,也就是说我们要按照订单的先后顺序依次为每份订单分配教室。如果在分配的过程中遇到一份订单无法完全满足,则需要停止教室的分配,通知当前申请人修改订单。这里的无法满足指从第sj天到第tj天中有至少一天剩余的教室数量不足dj个。
现在我们需要知道,是否会有订单无法完全满足。如果有,需要通知哪一个申请人修改订单。
思路:
由于是找到最先不适合的情况,且是按顺序出订单,那么可以考虑到二分接近答案。二分的判断条件是当前范围内的订单是否能够符合要求,首先就需要把判断范围内的各个时间段的订单累积起来,这里选择用差分统计各个时间段的订单,然后遍历比较是否有不符合的时间段,如果有一个不符合那就可以直接返回false,缩小比较范围;反之就是放大范围。
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define ll long long
using namespace std;
struct need{
int num,l,r;
}s[1000005];
int n,m;
int a[1000005];
bool check(int x){
int book[1000005];
memset(book,0,sizeof(book));
for(int i=1;i<=x;i++){
book[s[i].l]+=s[i].num;
book[s[i].r+1]-=s[i].num;
}
ll count=0;
for(int i=1;i<=n;i++){
count+=book[i];
if(count>a[i]){
return 0;
}
}
return 1;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=m;i++){
cin>>s[i].num>>s[i].l>>s[i].r;
}
int l=1,r=m;
if(check(r)){
cout<<0;
return 0;
}
int mid;
while(l<r){
mid=(l+r)/2;
if(check(mid)){
l=mid+1;
}
else r=mid;
}
cout<<-1<<endl<<l;
return 0;
}
1285

被折叠的 条评论
为什么被折叠?



