洛谷 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;
}

谢谢--zhengjun

posted @ 2022-06-10 20:02  A_zjzj  阅读(56)  评论(0编辑  收藏  举报