洛谷P1083 借教室---二分+差分

题目链接:https://www.luogu.com.cn/problem/P1083

题意:给定n天内,每天供应的教室数量ri和m个订单,表示第si到ti天用di个教室。按顺序执行订单,求第一个无法满足的订单编号

看到样例之后大致知道了做法。对于每个订单,把数组r的区间[si,ti]减去di,最后第一个出现某个ri<0时的订单编号就是答案。求第一个无法满足的订单编号,显然可以二分。因为如果前面的满足,那么不满足的一定都在后面;如果当前的已经不满足,那么第一个不满足的一定为在这个编号以及它的前面。由于是先进行一些区间加减,最后再判断是否有某个ri<0,所以可以用差分

#include<bits/stdc++.h>
using namespace std;

const int N=1e6+10;
struct st{int d,s,t;}a[N];
int c[N],r[N],pre[N],n,m,i,f,l,h;

bool check(int mid){
	memset(pre,0,sizeof(pre));
	for (i=1;i<=n;i++) c[i]=r[i]-r[i-1];
	for (i=1;i<=mid;i++){
	  c[a[i].s]-=a[i].d; c[a[i].t+1]+=a[i].d;
	}
	for (i=1;i<=n;i++){
	  pre[i]=pre[i-1]+c[i];
	  if (pre[i]<0) { //*
	  	f=-1; return false;
	  }
	}
	return true;
}

int main(){
	scanf("%d%d",&n,&m);
	for (i=1;i<=n;i++) scanf("%d",&r[i]);
	for (i=1;i<=m;i++) scanf("%d%d%d",&a[i].d,&a[i].s,&a[i].t);
	l=0; h=m; f=0;
	while (h-l>1){
	  int mid=(l+h)/2;
	  if (check(mid)) l=mid; else h=mid;
	}
    printf("%d
",f);
    if (f==-1) printf("%d",h);
	return 0;
}
原文地址:https://www.cnblogs.com/edmunds/p/13692039.html