90分暴力解法:
用线段树,初始值为该天的教室数,每个人来申请的时候在这段区间减去借走的数,然后查询最小值是否小于0,是就输出-1,否则继续。
(其实在vijos是可以直接A的,他们的评测机太快了)
#include <iostream> #define maxn 1000005 using namespace std; void scan(int &x) { char c; bool flag = false; while (!isdigit(c = getchar())) { if (c == '-') flag = true; } x = 0; do x = x * 10 + c - '0'; while (isdigit(c = getchar())); if (flag) x = -x; } int n, m, val[maxn]; namespace seg { struct node { int val, mark, minimum; } nds[maxn * 4]; void init(int l = 1, int r = n, int p = 1) { if (l == r) { nds[p].minimum = nds[p].val = val[l]; } else { int mid = (l + r) / 2; init(l, mid, p * 2); init(mid + 1, r, p * 2 + 1); nds[p].minimum = min(nds[p * 2].minimum, nds[p * 2 + 1].minimum); } } void add(int l, int r, int val, int p = 1, int ll = 1, int rr = n) { if (l == ll && r == rr) { nds[p].mark += val; nds[p].minimum += val; } else { int mid = (ll + rr) / 2; if (l <= mid) add(l, min(r, mid), val, p * 2, ll, mid); if (mid + 1 <= r) add(max(l, mid + 1), r, val, p * 2 + 1, mid + 1, rr); nds[p].minimum = min(nds[p * 2].minimum, nds[p * 2 + 1].minimum) + nds[p].mark; } } int query(int l, int r, int p = 1, int ll = 1, int rr = n) { if (l == ll && r == rr) { return nds[p].minimum; } else { int mid = (ll + rr) / 2; int ans = 0x7fffffff; if (l <= mid) ans = min(ans, query(l, min(r, mid), p * 2, ll, mid)); if (mid + 1 <= r) ans = min(ans, query(max(l, mid + 1), r, p * 2 + 1, mid + 1, rr)); return ans + nds[p].mark; } } } int main() { ios::sync_with_stdio(false); scan(n); scan(m); for (int i = 1; i <= n; i++) scan(val[i]); seg::init(1,n,1); int d, s, t; for (int i = 1; i <= m; i++) { scan(d); scan(s); scan(t); seg::add(s, t, -d); if (seg::query(s, t) < 0) { cout << -1 << endl << i; return 0; } } cout << 0; return 0; }