AcWing 503. 借教室
原题链接
简单
作者:
无双飞怪
,
2024-04-15 12:22:58
,
所有人可见
,
阅读 1
思路:
由于随着订单数量的增多 教室会越来越少
所以可以依次枚举订单的编号,当看到出现窟窿(即这个区间内某一天的教室数量少于当天提供的教室数量(rcm[i]))时
直接输出这个编号(这个就是排在最前面造成当天剩余教室数量rcm[i]<0的编号) return 0即可
更快?
那就二分(这里最开始没想到 反正给我的启发是凡是不会的就想二分和dp hh)
由于订单编号是有序的(可以这么理解 造成窟窿的可能性是随着编号的顺序递增的 那么就相当于一个排好序的递增数组,找这里面的val我们不都用二分吗) 那么就满足了二分的条件二段性
故:
二分编号 造窟窿用差分来实现
#include<bits/stdc++.h>
using namespace std;
const int N=1000010;
int n,m;
long long rcm[N],d[N],s[N],t[N],b[N];//不开long long见祖宗 10^15会爆int
bool check(int mid)
{
memset(b,0,sizeof b);//每次都要进来记得清空
for(int i=1;i<=mid;i++) b[s[i]]+=d[i],b[t[i]+1]-=d[i];//差分
for(int i=1;i<=n;i++)
{
b[i]+=b[i-1];//差分完记得求前缀和
if(b[i]>rcm[i]) return false;
}
return true;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) scanf("%d",&rcm[i]);
for(int i=1;i<=m;i++) scanf("%d%d%d",&d[i],&s[i],&t[i]);
int i=1,r=m;
while(l<r)
{
int mid=l+r>>1;
if(!check(mid)) r=mid;
else l=mid+1;
}
if(check(l)) cout<<0;
else cout<<-1<<endl<<-1;
return 0;
}