借教室 ——2012年NOIP全国联赛提高组

在大学期间,经常需要租借教室。大到院系举办活动,小到学习小组自习讨论,都需要

向学校申请借教室。教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样。

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

我们需要处理接下来n天的借教室信息,其中第i天学校有ri个教室可供租借。共有m份

订单,每份订单用三个正整数描述,分别为dj, sj, tj,表示某租借者需要从第sj天到第tj天租

借教室(包括第sj天和第tj天),每天需要租借dj个教室。

我们假定,租借者对教室的大小、地点没有要求。即对于每份订单,我们只需要每天提

供dj个教室,而它们具体是哪些教室,每天是否是相同的教室则不用考虑。

借教室的原则是先到先得,也就是说我们要按照订单的先后顺序依次为每份订单分配教

室。如果在分配的过程中遇到一份订单无法完全满足,则需要停止教室的分配,通知当前申

请人修改订单。这里的无法满足指从第sj天到第tj天中有至少一天剩余的教室数量不足dj个。

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

订单。

第一行包含两个正整数n, m,表示天数和订单的数量。

提高组  day2 

 

第二行包含n个正整数,其中第i个数为ri,表示第i天可用于租借的教室数量。

接下来有m行,每行包含三个正整数dj, sj, tj,表示租借的数量,租借开始、结束分别在

第几天。

每行相邻的两个数之间均用一个空格隔开。天数与订单均用从1开始的整数编号。

数据范围 1~2^6

算法 二分+括号法



#include<bits/stdc++.h>
typedef long long ll;const  ll MAXN=1000005;
ll t ,n,m,ans;
ll cy[MAXN],room[MAXN];
using namespace std;
struct node_1 {
ll d,s,t;
} day[MAXN];
ll  read() {
int f=1;ll r=0;
char c=getchar();
while(c<'0'||c>'9') {
if(c=='-')f=-1;
c=getchar();}
while(c>='0'&&c<='9') {
r=r*10+c-'0';
c=getchar();
}
return f*r;
}
bool pd(ll y) {
ll js=0;
for(ll j=1; j<=n; j++)cy[j]=0;
for(ll i=1; i<=y; i++) {
cy[day[i].s]+=day[i].d;
cy[day[i].t+1]-=day[i].d;
}
for(ll h=1; h<=n; h++)//注意每份订单都会影响每天的租借数量; 
{
js+=cy[h];
if(js > room[h])
  return false;
}
return true;
}
int main () {
n=read();m=read();
for(ll i=1; i<=n; i++) {
room[i]=read();
}
for(ll j=1; j<=m; j++) {
day[j].d=read();
day[j].s=read();
day[j].t=read();
}
     ll r=m,l=0,mid;
    if(pd(m)){
cout<<"0";return 0;}//
while(r-l>0)
{   mid=(l+r+1)/2;
  //cout<<"mid"<<mid<<endl;
if(pd(mid))l=mid;
        else r=mid-1;
if(r==l){
if(pd(r))ans=r;
else ans=r-1; 
}
//cout<<"left"<<l<<" "<<"right"<<r<<endl;
    }
    cout<<"-1"<<endl<<ans+1;
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值