借教室
题目的意思是只需要找一个人就可以了,还以为要找所有的人,怎么看也看不懂。
这道题懂的不是很彻底,挖
我们利用一个差分数组(差分数组:我们能在O(1)的时间内修改一段区间的值)
举个例子:来自hzwer
比如一开始数列a是0 0 0 0 0 0
前缀和0 0 0 0 0 0
3到5天需要2的教室
将a[3]+=2,a[6]-=2
数列变为0 0 2 0 0 -2
前缀和变为0 0 2 2 2 0
这样我们就很方便的修改了一段区间的值,当我们要查询一个点上的值,只需要求出其前缀和就行了
然后二分前mid 个人,这里满足单调性,只有一个是不满足的,并且我们可以知道是在我们的左边还是不在,那么这就和lower_bound查找差不多了,这个数比我小,那么我就在右边,这个数比我大,那么我就在左边
#include<iostream> #include<cstdio> #include<cstring> #define N 1000010 using namespace std; int n,m; int d[N],a[N],s[N],t[N],r[N]; inline int read() { int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){if(c=='-')f*=-1;c=getchar();} while(c>='0'&&c<='9'){x*=10;x+=c-'0';c=getchar();} return x*f; } bool C(int x) { int tot=0; memset(a,0,sizeof(a)); for(int i=1;i<=x;i++) { a[s[i]]+=d[i]; a[t[i]+1]-=d[i]; } for(int i=1;i<=n;i++) { tot+=a[i]; if(tot>r[i]) return false; } return true; } int main() { n=read(); m=read(); for(int i=1;i<=n;i++) { r[i]=read(); } for(int i=1;i<=m;i++) { d[i]=read(); s[i]=read(); t[i]=read(); } int l=1,r=m,ans=-1; while(l<r-1) { int mid=(l+r)/2; if(C(mid)) l=mid; else {ans=mid;r=mid;} } if(ans==-1) printf("0"); else printf("-1\n%d",ans); return 0; }