显然线段树可以搞……
不过常数需要优化的很小
另一种做法,
我们可以考虑二分答案
每次对于1--mid天维护前缀和判断即可
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 const int N=1000010; 5 int n,m,r[N],sum[N],s[N],d[N],t[N]; 6 int read(){ 7 int ss=0; 8 char ch=getchar(); 9 while (ch<'0'||ch>'9') 10 ch=getchar(); 11 while (ch>='0'&&ch<='9'){ 12 ss=ss*10+ch-'0'; 13 ch=getchar(); 14 } 15 return ss; 16 } 17 int check(int x){ 18 int now=0; 19 memset(sum,0,sizeof(sum)); 20 for (int i=1;i<=x;i++){ 21 sum[s[i]]-=d[i]; 22 sum[t[i]+1]+=d[i]; 23 } 24 for (int i=1;i<=n;i++){ 25 now+=sum[i]; 26 if (now+r[i]<0) 27 return 1; 28 } 29 return 0; 30 } 31 int main(){ 32 n=read(); 33 m=read(); 34 for (int i=1;i<=n;i++) 35 r[i]=read(); 36 for (int i=1;i<=m;i++){ 37 d[i]=read(); 38 s[i]=read(); 39 t[i]=read(); 40 } 41 int l=1,r=n; 42 while (l<r){ 43 int mid=(l+r)>>1; 44 if (check(mid)) 45 r=mid; 46 else 47 l=mid+1; 48 } 49 if (r==n) 50 printf("0"); 51 else 52 printf("-1\n%d",l); 53 return 0; 54 }