洛谷 P1083借教室题解--zhengjun
思路
一看嘛,立刻想到了线段树,然后呢,又不想打,感觉太长,于是呢,因为如果从第\(i\)个订单开始出问题,那么\(i+1\)以及以后的都会出问题,所以就可以二分,然后二分呢,重要的是\(check\)。
我们就要看看前面这么多订单每天的加在一起够不够,所以是区间修改,然后,就要\(O(n)\)枚举每一天看看会不会不够就可以了。
代码
#include<bits/stdc++.h>
#define maxn 1000001
using namespace std;
int n,m;
int a[maxn];
int d[maxn],l[maxn],r[maxn];
int f[maxn];
bool check(int x){
memset(f,0,sizeof(f));
for(int i=1;i<=x;i++){
f[l[i]]+=d[i];
f[r[i]+1]-=d[i];
}
int sum=0;
for(int i=1;i<=n;i++){
sum+=f[i];
if(sum>a[i])return 0;
}
return 1;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=m;i++)scanf("%d%d%d",&d[i],&l[i],&r[i]);
if(check(m)){
printf("0");
return 0;
}
int ll=0,rr=m,mid;
while(ll+1<rr){
mid=(ll+rr)>>1;
if(check(mid))ll=mid;
else rr=mid;
}
printf("-1\n%d",rr);
return 0;
}