借教室 洛谷(超详细教程)
思路:
请慢下来一点一点看你就会懂
1、我们要找到满足借教室的条件,如果可以借最后是零,如果不满足我们输出-1和这个人的序号。
2、我们会用到二分和前缀和以及差分
3、我们直接暴力肯定不能过。所以我们先在多少个人的区间上二分去找那个人(因为人是按照顺序去借教室的我们可以理解为有序)。假设有n个人那么这个区间就是1到n,我们在这上面二分。
4、接下来当我们二分一个人的时候我们把这个人前面所有人的教室加起来看看大不大于提供的教室数量。如果大了,我们就再二分小一点,反之就大一点。
前提是你会二分前缀和以及差分(不会没事,看我其他作品有的哦)
我把代码分了几个部分其实很好理解的,希望可以帮到你。
#include<bits/stdc++.h>
using namespace std;
const long long N = 1000000;
int n,m;
long long a[N],b[N],c[N],d[N],e[N]={0};
bool check(int mid)
{
memset(e,0,sizeof(e));//这个函数是初始化数组的
//这一部分是加起来二分前面所有人的借的教室数量
for(int i=1;i<=mid;i++)
{
int l=c[i],r=d[i],x=b[i];
e[l]+=x;
e[r+1]-=x;
}
//
//这就是比较这些人接的教室数量大不大于教室拥有量
for(int i=1;i<=n;i++)
{
e[i]+=e[i-1];
if(e[i]>a[i])
return true;
}
//
return false;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
int l=1,r=m,ans=0;
for(int i=1;i<=m;i++)
{
scanf("%lld%lld%lld",&b[i],&c[i],&d[i]);
}
//这上面的是录入数据(用long long啊)
//这就是二分模板了
while(l<=r)
{
int mid=(l+r)/2;
if(check(mid))
{
ans=mid;
r=mid-1;
}
else
l=mid+1;
}
//
if(ans==0)
{
cout<<0;
}
else
{
cout<<-1<<endl<<ans;
}
return 0;
}