自己YY出来的方法,时间复杂度为n*m,但实际上并没有这么多,codeVS上最慢的一组有300多ms。
对于每一个订单,在它的左端点加上需要的教室数量,在右端点加1的位置减去需要的教室数量。然后统计前缀和,如果有某个点的前缀和大于了当天教室的数量,那么就有的订单就有问题了,然后从订单编号从小到大统计在订单区间的教室数量,保存恰好不能满足的那个订单;对于之后不满足题意的前缀和,统计订单的最大编号不能超过之前保存的订单标号。
#include<cstdio> #define MAXN 1000005 using namespace std; typedef long long LL; struct T { LL d; int s,t; }a[MAXN]; int n,m; LL cl[MAXN]; LL sum[MAXN]; LL t[MAXN]; int maxn; int pos = 123456789; int main() { //freopen("classroom.in","r",stdin); //freopen("classroom.out","w",stdout); scanf("%d%d",&n,&m); for(int i = 1; i <= n; i++) scanf("%lld",&cl[i]); for(int i = 1; i <= m; i++) { scanf("%lld%d%d",&a[i].d,&a[i].s,&a[i].t); if(a[i].t > maxn) maxn = a[i].t; t[a[i].s] += a[i].d; t[a[i].t] += a[i].d; if(t[a[i].s] > cl[a[i].s]&&pos > i) { pos = i; } if(t[a[i].t] > cl[a[i].t]&&pos > i) { pos = i; } sum[a[i].s] += a[i].d; sum[a[i].t+1] -= a[i].d; } for(int i = 1; i <= maxn; i++) { sum[i] += sum[i-1]; } for(int i = 1; i <= n; i++) { if(sum[i] > cl[i])//需求超过教室数量 { int temp = 0; for(int j = 1; j <= m; j++)//统计在订单区间内的和 { if(j > pos) break;//不能超过之前订单的最大编号 if(a[j].s <= i&&a[j].t >= i) temp += a[j].d; if(temp > cl[i]) { pos = j;//保存订单的最大编号 break; } } } } if(pos == 123456789) printf("0\n"); else { printf("-1\n"); printf("%d\n",pos); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-16 10:30:56