Description
Input
Output
Sample Input
4 3 2 5 4 3 2 1 3 3 2 4 4 2 4
Sample Output
-1 2
Data Constraint
Hint
第一份订单满足后,4天剩余教室分数分别为0,3,2,3. 第二份订单要求第二天到第四天每天提供三个教室,而第三天剩余的教室数为二,因此无法满足。分配停止通知第二个申请人修改订单。
10% -> 1<=n,m<=10
30% -> 1<=n,m<=1000
70% -> 1<=n,m<=100000
100% -> 1<=n,m<=1000000, 0<=ri,dj<=1000000000, 1<=sj<=tj<=n
这道题很明显可以用线段树。
然而区间修改有比它更快,更好写的离线方法,差分数组。
首先这道题需要二分答案,接着用差分数组写check函数。b[i]=a[i]-a[i-1];b[1]=a[1];b为差分数组
我们可以发现一个性质(此处不做证明)对与a[i]的[l,r]区间减少s
相当与在b[l]-s,b[r+1]+s;
check(x)时,先求出b,然后进行修改,在之后判断修改过后的b数组根据a[i]=b[i]+a[i-1]判断a[i]<0即可返回false
#include<cstdio> const int N=1e6+5; int x[N],y[N],z[N],l[N],r[N],sl[N],n,m; bool f(int a) { for(int i=1;i<=n;i++) y[i]=x[i]-x[i-1]; for(int i=1;i<=a;i++) y[l[i]]-=sl[i],y[r[i]+1]+=sl[i]; for(int i=1;i<=n;i++) { z[i]=z[i-1]+y[i]; if(z[i]<0) return 0; } return 1; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&x[i]); for(int i=1;i<=m;i++) scanf("%d%d%d",&sl[i],&l[i],&r[i]); int l=0,r=m+1; while(l<r-1) { int mid=(l+r)>>1; if(f(mid)) l=mid; else r=mid; } if(r==m+1) putchar(‘0‘); else printf("-1\n%d",r); return 0; }
时间: 2024-10-12 14:42:10