类型:二分答案+差分
传送门:>Here<
题意:学校规定第$i$天只能借$r[i]$间教室。现给出$M$个订单,每个订单描述要在$s[i]$到$t[i]$期间每天借$d[i]$间教室。原则是先到先得,问第一个无法满足的订单是第几个?
解题思路
这题暴力分很好拿呀……打了10分钟拿到30分。后来发现数组开小了,改大之后竟然变成了45分!这题的暴力是PJ-难度啊……
然后偷看一眼标签马上知道了二分答案,但是要做到$O(n)$验证,前缀和的空间复杂度是$mn$的啊……然后突然之间想到,不需要对每一天维护前缀和,只需要维护一个差分数组就好了!于是AC
希望今年也能碰到这样的良心题啊!(样例并不良心)
Code
/*By DennyQi 2018.8.16*/ #include <cstdio> #include <queue> #include <cstring> #include <algorithm> #define r read() #define Max(a,b) (((a)>(b)) ? (a) : (b)) #define Min(a,b) (((a)<(b)) ? (a) : (b)) using namespace std; typedef long long ll; const int MAXN = 1000010; const int MAXM = 27010; const int INF = 1061109567; inline int read(){ int x = 0; int w = 1; register int c = getchar(); while(c ^ '-' && (c < '0' || c > '9')) c = getchar(); if(c == '-') w = -1, c = getchar(); while(c >= '0' && c <= '9') x = (x<<3) + (x<<1) + c - '0', c = getchar();return x * w; } int N,M,flg,L,R,Mid,Ans; int a[MAXN],d[MAXN],s[MAXN],t[MAXN],cf[MAXN]; inline bool judge(int k){ int u = 0; memset(cf, 0, sizeof(cf)); for(int i = 1; i <= k; ++i){ cf[s[i]] -= d[i]; cf[t[i]+1] += d[i]; } for(int i = 1; i <= N; ++i){ u += cf[i]; if(u+a[i] < 0) return 1; } return 0; } int main(){ N = r, M = r; for(int i = 1; i <= N; ++i) a[i] = r; for(int i = 1; i <= M; ++i) d[i] = r, s[i] = r, t[i] = r; L = 0, R = M+1; while(L <= R){ Mid = (L+R) / 2; if(judge(Mid)) R = Mid - 1; else Ans = Mid, L = Mid+1; } if(Ans+1 <= M) printf("-1\n%lld", Ans+1); else printf("0"); return 0; }