1. 程式人生 > >洛谷1083(差分+二分 or 線段樹)

洛谷1083(差分+二分 or 線段樹)

urn spa min while 線段 turn 通過 return int

第一種方法:可以二分最大天數訂單的答案然後通過差分求一下是否可行。

 1 const int maxn = 1e6 + 5;
 2 int n, m, a[maxn], ans;
 3 struct section {
 4     int cnt, l, r;
 5 }b[maxn];
 6 int c[maxn], sum[maxn];
 7 
 8 inline bool ok(int now) {
 9     init(c, 0);
10     rep(i, 1, now) {
11         auto tmp = b[i];
12         c[tmp.l] -= tmp.cnt;
13 c[tmp.r + 1] += tmp.cnt; 14 } 15 rep(i, 1, n) { 16 sum[i] = sum[i - 1] + c[i]; 17 if (sum[i] + a[i] < 0) return false; 18 } 19 return true; 20 } 21 22 int main() { 23 read(n), read(m); 24 rep(i, 1, n) read(a[i]); 25 rep(i, 1, m) {
26 read(b[i].cnt); 27 read(b[i].l); 28 read(b[i].r); 29 } 30 31 int l = 1, r = m; 32 while (l <= r) { 33 int mid = (l + r) >> 1; 34 if (ok(mid)) { 35 l = mid + 1; 36 } else { 37 ans = mid; 38 r = mid - 1
; 39 } 40 } 41 42 if (!ans) writeln(0); 43 else { 44 writeln(-1); 45 writeln(ans); 46 } 47 return 0; 48 }

第二種方法:無腦插一棵殘缺的線段樹板子即可:

 1 const int maxn = 1e6 + 5;
 2 int n, m;
 3 struct Node {
 4     int l, r, minn, tag;
 5 }t[maxn << 2];
 6 #define ls(p)    p << 1
 7 #define rs(p)    p << 1 | 1
 8 
 9 void Build(int l, int r, int p) {
10     t[p].l = l, t[p].r = r;
11     if (l == r) {
12         read(t[p].minn);
13         t[p].tag = 0;
14         return;
15     }
16     int mid = (l + r) >> 1;
17     Build(l, mid, ls(p));
18     Build(mid + 1, r, rs(p));
19     t[p].minn = min(t[ls(p)].minn, t[rs(p)].minn);
20 }
21 
22 void Push_down(int p) {
23     if (t[p].tag) {
24         t[ls(p)].minn += t[p].tag;
25         t[rs(p)].minn += t[p].tag;
26         t[ls(p)].tag += t[p].tag;
27         t[rs(p)].tag += t[p].tag;
28         t[p].tag = 0;
29     }
30 }
31 
32 void Modify(int l, int r, int p, int k) {
33     if (l <= t[p].l && t[p].r <= r) {
34         t[p].minn += k;
35         t[p].tag += k;
36         return;
37     }
38     Push_down(p);
39     int mid = (t[p].l + t[p].r) >> 1;
40     if (l <= mid)    Modify(l, r, ls(p), k);
41     if (mid < r)    Modify(l, r, rs(p), k);
42     t[p].minn = min(t[ls(p)].minn, t[rs(p)].minn);
43 }
44 
45 int main() {
46     read(n), read(m);
47     Build(1, n, 1);
48     rep(i, 1, m) {
49         int cnt, l, r;
50         read(cnt), read(l), read(r);
51         Modify(l, r, 1, -cnt);
52         if (t[1].minn < 0) {
53             writeln(-1);
54             writeln(i);
55             return 0;
56         }
57     }
58     writeln(0);
59     return 0;
60 }

洛谷1083(差分+二分 or 線段樹)