codeforces round#783 div2 D
阿新 • • 發佈:2022-04-20
思路:
首先考慮字首和為負數和0,肯定是每次只考慮一個數字最優;
然後考慮dp f[i]=max(f[j]+i-j),其中j+1到i的和為正數,
就是在前i個裡找字首和小於si並且最大的f[j],因為f[j]中j已經選擇,
所以是j+1到i,使用樹狀陣列維護字首和就可以查詢,更新的時候可以
賦值為f[j]-j,這樣求出來的最大值再加i就是f[i]
程式碼:
const int N = 500010; int c[N]; int ask(int x) { int res = -inf; for (;x;x -= lowbit(x)) res = max(res, c[x]); return res; } void add(int x, int y) { for (;x < N;x += lowbit(x)) c[x] = max(c[x], y); } int f[N], a[N], s[N]; vector<int> v; int find(int x) { return lower_bound(all(v), x) - v.begin() + 1; } void solve() { int n = read(); v.clear(); for (int i = 1;i <= n;i++) a[i] = read(), s[i] = s[i - 1] + a[i], v.push_back(s[i]); sort(all(v)); v.erase(unique(all(v)), v.end()); for (int i = 0;i <= n + 10;i++) c[i] = -inf; int ans = 0; f[0] = 0; for (int i = 1;i <= n;i++) f[i] = -inf; for (int i = 1;i <= n;i++) { int x = find(s[i]); int t = ask(x - 1); int val = 0; if (a[i] > 0) val = 1; else if (a[i] == 0) val = 0; else val = -1; int d = -inf; if (s[i] > 0) d = i; f[i] = max({ f[i - 1] + val, t + i,d }); add(x, f[i] - i); } printf("%lld\n", f[n]); clean(); }