#include <bits/stdc++.h> using namespace std; #define ll long long const int R = 512 * 1024 * 2; const int maxn = 5e5; ll a[maxn + 5]; ll tree[2 * R]; ll lazy[2 * R]; ll sum[maxn + 5]; ll dp[maxn + 5]; void update(int id, ll val){ tree[id] += val; lazy[id] += val; } void push(int id){ update(2 * id, lazy[id]); update(2 * id + 1, lazy[id]); lazy[id] = 0; } void add(int beg, int end, ll val, int id = 1, int l = 1, int r = R){ if(l > end || r < beg) return; if(beg <= l && r <= end){ update(id,val); return; } push(id); int left = 2 * id; int right = 2 * id + 1; int mid = (l + r) / 2; add(beg,end,val,left,l,mid); add(beg,end,val,right,mid + 1,r); tree[id] = max(tree[left],tree[right]); } void addOne(int pos, ll val, int id = 1,int l = 1, int r = R){ if(l > pos || r < pos) return; if(l == r && l == pos){ if(val > tree[id]) tree[id] = val; return; } push(id); int left = 2 * id; int right = 2 * id + 1; int mid = (l + r) / 2; addOne(pos,val,left,l,mid); addOne(pos,val,right,mid + 1,r); tree[id] = max(tree[left],tree[right]); } int query(int beg, int end, int id = 1, int l = 1, int r = R){ if(l > end || r < beg) return 1e9; int left = 2 * id; int right = 2 * id + 1; int mid = (l + r) / 2; if(l == r){ if(tree[id] >= 0) return l; else return 1e9; } push(id); if(beg <= l && r <= end){ int ret = 1e9; if(tree[left] >= 0) ret = query(beg,end,left,l,mid); else ret = query(beg,end,right,mid + 1,r); tree[id] = max(tree[left],tree[right]); return ret; } int tmp = query(beg,end,left,l,mid); if(tmp == 1e9) tmp = query(beg,end,right,mid + 1,r); tree[id] = max(tree[left],tree[right]); return tmp; } int main(){ ios_base::sync_with_stdio(0);cin.tie(0); int n; cin >> n; for(int i = 1; i <= n; i++) dp[i] = 1e18; add(1,2 * n, -1e18); for(int i = 1; i <= n; i++){ cin >> a[i]; sum[i] = sum[i - 1] + a[i]; } for(ll i = 1; i <= n; i++){ /// c1 + n, c2 + n - 1, c3 + n - 2 ... add(1, 2 * n, a[i]); /// dodać wszędzie ll cost = query(1,2*n); cost -= (n - i + 1); ll tmp = 1e18; if(a[i] >= 0) tmp = dp[i - 1]; dp[i] = min(tmp,cost); int pos = dp[i - 1] + n - i + 1; if(pos <= 2 * n) addOne(pos,a[i]); /// dodać nowego, jesli się da (zmaksować) } if(sum[n] < 0LL) cout << -1 << '\n'; else cout << dp[n] << '\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 | #include <bits/stdc++.h> using namespace std; #define ll long long const int R = 512 * 1024 * 2; const int maxn = 5e5; ll a[maxn + 5]; ll tree[2 * R]; ll lazy[2 * R]; ll sum[maxn + 5]; ll dp[maxn + 5]; void update(int id, ll val){ tree[id] += val; lazy[id] += val; } void push(int id){ update(2 * id, lazy[id]); update(2 * id + 1, lazy[id]); lazy[id] = 0; } void add(int beg, int end, ll val, int id = 1, int l = 1, int r = R){ if(l > end || r < beg) return; if(beg <= l && r <= end){ update(id,val); return; } push(id); int left = 2 * id; int right = 2 * id + 1; int mid = (l + r) / 2; add(beg,end,val,left,l,mid); add(beg,end,val,right,mid + 1,r); tree[id] = max(tree[left],tree[right]); } void addOne(int pos, ll val, int id = 1,int l = 1, int r = R){ if(l > pos || r < pos) return; if(l == r && l == pos){ if(val > tree[id]) tree[id] = val; return; } push(id); int left = 2 * id; int right = 2 * id + 1; int mid = (l + r) / 2; addOne(pos,val,left,l,mid); addOne(pos,val,right,mid + 1,r); tree[id] = max(tree[left],tree[right]); } int query(int beg, int end, int id = 1, int l = 1, int r = R){ if(l > end || r < beg) return 1e9; int left = 2 * id; int right = 2 * id + 1; int mid = (l + r) / 2; if(l == r){ if(tree[id] >= 0) return l; else return 1e9; } push(id); if(beg <= l && r <= end){ int ret = 1e9; if(tree[left] >= 0) ret = query(beg,end,left,l,mid); else ret = query(beg,end,right,mid + 1,r); tree[id] = max(tree[left],tree[right]); return ret; } int tmp = query(beg,end,left,l,mid); if(tmp == 1e9) tmp = query(beg,end,right,mid + 1,r); tree[id] = max(tree[left],tree[right]); return tmp; } int main(){ ios_base::sync_with_stdio(0);cin.tie(0); int n; cin >> n; for(int i = 1; i <= n; i++) dp[i] = 1e18; add(1,2 * n, -1e18); for(int i = 1; i <= n; i++){ cin >> a[i]; sum[i] = sum[i - 1] + a[i]; } for(ll i = 1; i <= n; i++){ /// c1 + n, c2 + n - 1, c3 + n - 2 ... add(1, 2 * n, a[i]); /// dodać wszędzie ll cost = query(1,2*n); cost -= (n - i + 1); ll tmp = 1e18; if(a[i] >= 0) tmp = dp[i - 1]; dp[i] = min(tmp,cost); int pos = dp[i - 1] + n - i + 1; if(pos <= 2 * n) addOne(pos,a[i]); /// dodać nowego, jesli się da (zmaksować) } if(sum[n] < 0LL) cout << -1 << '\n'; else cout << dp[n] << '\n'; return 0; } |