CF783-D Optimal Partition
阿新 • • 發佈:2022-04-20
// dp + fenwick + 離散 + 字首和 // 可以證明:對於最優劃分,分數為0和負數的區間一定可以優化成長度只有1的子段 // 現在只考慮分數為正數的情況:f[i] = max{f[j] - j} + i; 則維護一棵Fenwick Tree即可 // f[i] = max(f[i - 1] + (a[i] < 0 ? -1 : 0), fen.sum(s[i])); #include <bits/stdc++.h> using namespace std; using ll = long long; const int INF = 1e9; struct Fenwick { const int n; std::vector<int> a; Fenwick(int n) : n(n), a(n, -INF) {} void add(int x, int v) { for (int i = x + 1; i <= n; i += i & -i) { a[i - 1] = std::max(a[i - 1], v); } } int sum(int x) { int ans = -INF; for (int i = x; i > 0; i -= i & -i) { ans = std::max(ans, a[i - 1]); } return ans; } }; void solve(){ int n; cin >> n; vector<int>a(n); for(int i = 0; i < n; ++i) cin >> a[i]; vector<ll>s(n + 1); for(int i = 1; i <= n; ++i) s[i] = s[i - 1] + a[i - 1]; auto v = s; sort(v.begin(), v.end()); for(int i = 0; i <= n; ++i) s[i] = lower_bound(v.begin(), v.end(), s[i]) - v.begin(); Fenwick fen(n + 1); vector<int>f(n + 1); for(int i = 1; i <= n; ++i) { fen.add(s[i - 1], f[i - 1] - i + 1); f[i] = max(f[i - 1] + (a[i - 1] < 0 ? -1 : 0), i + fen.sum(s[i])); } cout << f[n] << endl; } int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int T; cin>>T; while(T--){ solve(); } return 0; }