分析
看到数据范围就要至少 O ( n ∗ l o g 2 n ) O(n*log_2n) O(n∗log2n)时间完成。
因为有区间加的处理,所以就用差分就行,具体实现就是先做一个差分数组(前缀差),然后修改的话就 b [ l ] + = c , b [ r + 1 ] − = c b[l]+=c,b[r+1]-=c b[l]+=c,b[r+1]−=c就将区间 [ l , r ] [l,r] [l,r] 内的值都减去了 c c c 。这样子是线性的。
但是如果一个个枚举,就肯定不行,因为只要找到第一个不满足条件的,所以直接二分第一个人,看看是否满足条件,这样就能找到第一个人了。
上代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,b[1000100],r[1000100];
int d[1000100],s[1000100],t[1000100];
int pd(int k)
{
for(int i=1;i<=n;i++)
{
b[i]=r[i]-r[i-1];
}
for(int i=1;i<=k;i++)
{
b[s[i]]-=d[i];
b[t[i]+1]+=d[i];
}
for(int i=1;i<=n;i++)
{
b[i]+=b[i-1];
}
// for(int i=1;i<=n;i++) cout<<b[i]<<' ';
// cout<<endl;
for(int i=1;i<=n;i++)
{
if(b[i]<0) return 0;
}
return 1;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%d",&r[i]);
}
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&d[i],&s[i],&t[i]);
}
int l=1,r=m,mid;
while(l<r)
{
mid=(l+r)>>1;
if(pd(mid)) l=mid+1;
else r=mid;
}
if(r==m) cout<<0;
else cout<<-1<<endl<<l;
return 0;
}