#ifndef LOCAL #pragma GCC optimize("O3") #endif #include <bits/stdc++.h> using namespace std; #define sim template <class c #define mor > muu & operator<<( #define ris return *this #define R22(r) sim>typename enable_if<1 r sizeof(dud<c>(0)),muu&>::type operator<<(c g) { #define R23(r) sim, size_t N>typename enable_if<N r std::tuple_size<c>::value,muu&>::type operator<<(zub<c,N> sim> struct rge {c b, e;}; sim> rge<c> range(c i, c j) {return rge<c>{i, j};} sim> auto dud(c*r)->decltype(cerr << *r); sim> char dud(...); sim, size_t N> struct zub {c x;}; struct muu { #ifdef LOCAL #define qel(t) sim, class d, class...e mor t<c,d,e...> r){ris << *(d*)&r;} qel(queue) qel(priority_queue) qel(stack) stringstream a; ~muu() {cerr << a.str() << endl;} R22(<) a << boolalpha << g; ris;} R22(==) ris << range(begin(g), end(g));} sim mor rge<c> u) { a << "["; for (c i = u.b; i != u.e; ++i) *this << ", " + 2 * (i == u.b) << *i; ris << "]"; } sim, class m mor pair <m,c>r){ris << "(" << r.first << ", " << r.second << ")";} sim, class...m mor tuple<c,m...>r){ris << zub<tuple<c,m...>,0>{r};} R23(!=) g) {ris << (N ? ", " : "(") << get<N>(g.x) << zub<c, N + 1>{g.x};} R23(==) ) {ris << ")";} #else sim mor const c&){ris;} #endif }; #define imie(r...) "[" #r ": " << (r) << "] " #define arr(a, i) "[" #a imie(i) ": " << a[i] << "] " #define range(a, b) "[[" #a ", " #b "): " << range(a, b) << "] " #define debug muu() << __FUNCTION__ << "#" << __LINE__ << ": " #define arr2(a, i, j) "[" #a imie(i) imie(j) ": " << a[i][j] << "] " #define imask(r...) "[" #r ": " << bitset<8 * sizeof(r)>(r) << "] " using pii = pair <int, int>; using ll = long long; using ull = unsigned long long; using ld = long double; using Pii = pii; using vpii = vector<pii>; using unt = unsigned int; using vi = vector <int>; using pll = pair <ll, ll>; using vpll = vector <pll>; sim> void mini(c &a, c b) {if (a > b) a = b;} sim> void maxi(c &a, c b) {if (a < b) a = b;} #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> using namespace __gnu_pbds; sim, class cmp = less<c> > using ordered_set = tree<c, null_type, cmp, rb_tree_tag, tree_order_statistics_node_update>; const int maxn = 6e5; const int inf = 1e9; int A[maxn]; int dp[maxn]; ll sums[maxn]; int n; struct Tree { vi V; int d; Tree(int sz) { d = 1; while(d <= sz) d *= 2; V.assign(2 * d, inf); } void update(int val, int ind) { ind += d; if (V[ind] < val) return; V[ind] = val; ind /= 2; while(ind) { int l = 2 * ind; int r = l + 1; V[ind] = min(V[l], V[r]); ind /= 2; } } int query(int l, int r) { l += d; r += d; int res = min(V[l], V[r]); while(l / 2 != r / 2) { if (l % 2 == 0) res = min(res, V[l+1]); if (r % 2 == 1) res = min(res, V[r-1]); l /= 2; r /= 2; } return res; } }; int main() { scanf("%d", &n); for(int i = 1; i <= n; ++i) scanf("%d", &A[i]); ll sum = 0; for(int i = 1; i <= n; ++i) { sum += A[i]; sums[i] = sum; } set<ll> S; for(int i = 0; i <= n; ++i) S.insert(sums[i]); int ind = 0; map<ll, int> M; for(int s : S) M[s] = ind++; Tree T(ind + 1); if(sum < 0) { puts("-1"); return 0; } dp[0] = 0; T.update(0, M[0]); for(int i = 1; i <= n; ++i) { dp[i] = inf; if (sums[i] < 0) continue; dp[i] = min(i - 1 + T.query(0, M[sums[i]]), inf); T.update(dp[i] - i, M[sums[i]]); //~ for (int j = 0; j < i; ++j) //~ { //~ if (sums[i] >= sums[j]) //~ dp[i] = min(dp[i], dp[j] + i - j - 1); //~ } } printf("%d\n", dp[n]); }
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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | #ifndef LOCAL #pragma GCC optimize("O3") #endif #include <bits/stdc++.h> using namespace std; #define sim template <class c #define mor > muu & operator<<( #define ris return *this #define R22(r) sim>typename enable_if<1 r sizeof(dud<c>(0)),muu&>::type operator<<(c g) { #define R23(r) sim, size_t N>typename enable_if<N r std::tuple_size<c>::value,muu&>::type operator<<(zub<c,N> sim> struct rge {c b, e;}; sim> rge<c> range(c i, c j) {return rge<c>{i, j};} sim> auto dud(c*r)->decltype(cerr << *r); sim> char dud(...); sim, size_t N> struct zub {c x;}; struct muu { #ifdef LOCAL #define qel(t) sim, class d, class...e mor t<c,d,e...> r){ris << *(d*)&r;} qel(queue) qel(priority_queue) qel(stack) stringstream a; ~muu() {cerr << a.str() << endl;} R22(<) a << boolalpha << g; ris;} R22(==) ris << range(begin(g), end(g));} sim mor rge<c> u) { a << "["; for (c i = u.b; i != u.e; ++i) *this << ", " + 2 * (i == u.b) << *i; ris << "]"; } sim, class m mor pair <m,c>r){ris << "(" << r.first << ", " << r.second << ")";} sim, class...m mor tuple<c,m...>r){ris << zub<tuple<c,m...>,0>{r};} R23(!=) g) {ris << (N ? ", " : "(") << get<N>(g.x) << zub<c, N + 1>{g.x};} R23(==) ) {ris << ")";} #else sim mor const c&){ris;} #endif }; #define imie(r...) "[" #r ": " << (r) << "] " #define arr(a, i) "[" #a imie(i) ": " << a[i] << "] " #define range(a, b) "[[" #a ", " #b "): " << range(a, b) << "] " #define debug muu() << __FUNCTION__ << "#" << __LINE__ << ": " #define arr2(a, i, j) "[" #a imie(i) imie(j) ": " << a[i][j] << "] " #define imask(r...) "[" #r ": " << bitset<8 * sizeof(r)>(r) << "] " using pii = pair <int, int>; using ll = long long; using ull = unsigned long long; using ld = long double; using Pii = pii; using vpii = vector<pii>; using unt = unsigned int; using vi = vector <int>; using pll = pair <ll, ll>; using vpll = vector <pll>; sim> void mini(c &a, c b) {if (a > b) a = b;} sim> void maxi(c &a, c b) {if (a < b) a = b;} #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> using namespace __gnu_pbds; sim, class cmp = less<c> > using ordered_set = tree<c, null_type, cmp, rb_tree_tag, tree_order_statistics_node_update>; const int maxn = 6e5; const int inf = 1e9; int A[maxn]; int dp[maxn]; ll sums[maxn]; int n; struct Tree { vi V; int d; Tree(int sz) { d = 1; while(d <= sz) d *= 2; V.assign(2 * d, inf); } void update(int val, int ind) { ind += d; if (V[ind] < val) return; V[ind] = val; ind /= 2; while(ind) { int l = 2 * ind; int r = l + 1; V[ind] = min(V[l], V[r]); ind /= 2; } } int query(int l, int r) { l += d; r += d; int res = min(V[l], V[r]); while(l / 2 != r / 2) { if (l % 2 == 0) res = min(res, V[l+1]); if (r % 2 == 1) res = min(res, V[r-1]); l /= 2; r /= 2; } return res; } }; int main() { scanf("%d", &n); for(int i = 1; i <= n; ++i) scanf("%d", &A[i]); ll sum = 0; for(int i = 1; i <= n; ++i) { sum += A[i]; sums[i] = sum; } set<ll> S; for(int i = 0; i <= n; ++i) S.insert(sums[i]); int ind = 0; map<ll, int> M; for(int s : S) M[s] = ind++; Tree T(ind + 1); if(sum < 0) { puts("-1"); return 0; } dp[0] = 0; T.update(0, M[0]); for(int i = 1; i <= n; ++i) { dp[i] = inf; if (sums[i] < 0) continue; dp[i] = min(i - 1 + T.query(0, M[sums[i]]), inf); T.update(dp[i] - i, M[sums[i]]); //~ for (int j = 0; j < i; ++j) //~ { //~ if (sums[i] >= sums[j]) //~ dp[i] = min(dp[i], dp[j] + i - j - 1); //~ } } printf("%d\n", dp[n]); } |