分析
二分+差分+前缀和=
二分当前到第几个申请人
c[i]为差分数组
设租借开始日期为x ,终止日期为y,租借数量为w
c[x]+=w ; c[y+1]-=w;
对差分数组求前缀和:
sum[i]=sum[i-1]+c[i] 此时sum[i]代表第i天要租借的教室总数
若大于r[i],返回false
全部求完后所有sum[i]若都小于r[i],就返回true
二分答案提高效率真的重要orz
代码如下
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1000050;
int n,m,s[N],t[N];
ll r[N],d[N],c[N],sum[N];
ll read(){
ll sum=0,f=1;
char ch=getchar();
while(ch>'9'||ch<'0')
{
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
sum=(sum<<3)+(sum<<1)+ch-'0';
ch=getchar();
}
return sum*f;
}
int check(int len){
memset(c,0,sizeof(c));
for(int i=1;i<=len;i++)
{
c[s[i]]+=d[i];c[t[i]+1]-=d[i];
}
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+c[i];
if(sum[i]>r[i])return 0;
}
return 1;
}
int main(){
// freopen("classroom.in","r",stdin);
// freopen("classroom.out","w",stdout);
n=read();
m=read();
for(int i=1;i<=n;i++)
r[i]=read();
for(int i=1;i<=m;i++)
{
d[i]=read();
s[i]=read();
t[i]=read();
}
int l=1,r=m,mid;
while(l<=r)
{
mid=l+(r-l)/2;
if(check(mid)){
l=mid+1;
}
else{
r=mid-1;
}
}
if(r==m)cout<<0;
else cout<<-1<<endl<<l;
return 0;
}