#include <iostream> #include <set> using namespace std; const int N_MAX = 500 * 1000 + 5; const int INF = 1000 * 1000 * 1000; const int T = 1048576; int tree[2 * T]; int querry(int a, int b) { a += T; b += T; int w = min(tree[a], tree[b]); while (a / 2 != b / 2) { if (a % 2 == 0) w = min(w, tree[a + 1]); if (b % 2 == 1) w = min(w, tree[b - 1]); a /= 2; b /= 2; } return w; } void update(int a, int x) { a += T; if (tree[a] <= x) return; tree[a] = x; while (a > 1) { a /= 2; tree[a] = min(tree[2 * a], tree[2 * a + 1]); } } int miasta[N_MAX + 1]; long long offset[N_MAX + 1]; long long index[N_MAX + 1]; int dp[N_MAX + 1]; set<long long> wartosci; set<pair<long long, int>> indeksy; int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; if (n == 0) { cout << "0\n"; return 0; } if (n == 1) { int x; cin >> x; if (x >= 0) cout << "0\n"; else cout << "-1\n"; return 0; } for (int i = 0; i < n; i++) { cin >> miasta[i]; } offset[0] = -miasta[0]; index[0] = 0; dp[0] = INF; for (int i = 1; i < n; i++) { offset[i] = offset[i - 1] - miasta[i]; index[i] = offset[i] + miasta[i]; dp[i] = INF; } for (int i = 0; i < n; i++) { wartosci.insert(offset[i]); wartosci.insert(index[i]); } int nr = 0; for (auto &x : wartosci) { indeksy.insert(make_pair(x, nr++)); } int maxIndex = nr - 1; for (int i = 0; i < n; i++) { offset[i] = indeksy.lower_bound(make_pair(offset[i], -1))->second; index[i] = indeksy.lower_bound(make_pair(index[i], -1))->second; } for (int i = T + maxIndex; i > 0; i--) { tree[i] = INF; } if (miasta[0] >= 0) dp[0] = 0; update((int)index[0], 0); for (int i = 1; i < n; i++) { if (dp[i - 1] < INF && miasta[i] >= 0) dp[i] = dp[i - 1]; dp[i] = min(querry((int)offset[i], maxIndex) + i, dp[i]); update((int)index[i], dp[i - 1] - i); } if (dp[n - 1] < INF) cout << dp[n - 1] << "\n"; else cout << -1 << "\n"; return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | #include <iostream> #include <set> using namespace std; const int N_MAX = 500 * 1000 + 5; const int INF = 1000 * 1000 * 1000; const int T = 1048576; int tree[2 * T]; int querry(int a, int b) { a += T; b += T; int w = min(tree[a], tree[b]); while (a / 2 != b / 2) { if (a % 2 == 0) w = min(w, tree[a + 1]); if (b % 2 == 1) w = min(w, tree[b - 1]); a /= 2; b /= 2; } return w; } void update(int a, int x) { a += T; if (tree[a] <= x) return; tree[a] = x; while (a > 1) { a /= 2; tree[a] = min(tree[2 * a], tree[2 * a + 1]); } } int miasta[N_MAX + 1]; long long offset[N_MAX + 1]; long long index[N_MAX + 1]; int dp[N_MAX + 1]; set<long long> wartosci; set<pair<long long, int>> indeksy; int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); int n; cin >> n; if (n == 0) { cout << "0\n"; return 0; } if (n == 1) { int x; cin >> x; if (x >= 0) cout << "0\n"; else cout << "-1\n"; return 0; } for (int i = 0; i < n; i++) { cin >> miasta[i]; } offset[0] = -miasta[0]; index[0] = 0; dp[0] = INF; for (int i = 1; i < n; i++) { offset[i] = offset[i - 1] - miasta[i]; index[i] = offset[i] + miasta[i]; dp[i] = INF; } for (int i = 0; i < n; i++) { wartosci.insert(offset[i]); wartosci.insert(index[i]); } int nr = 0; for (auto &x : wartosci) { indeksy.insert(make_pair(x, nr++)); } int maxIndex = nr - 1; for (int i = 0; i < n; i++) { offset[i] = indeksy.lower_bound(make_pair(offset[i], -1))->second; index[i] = indeksy.lower_bound(make_pair(index[i], -1))->second; } for (int i = T + maxIndex; i > 0; i--) { tree[i] = INF; } if (miasta[0] >= 0) dp[0] = 0; update((int)index[0], 0); for (int i = 1; i < n; i++) { if (dp[i - 1] < INF && miasta[i] >= 0) dp[i] = dp[i - 1]; dp[i] = min(querry((int)offset[i], maxIndex) + i, dp[i]); update((int)index[i], dp[i - 1] - i); } if (dp[n - 1] < INF) cout << dp[n - 1] << "\n"; else cout << -1 << "\n"; return 0; } |