[BZOJ4709][JSOI2011]檸檬[決策單調性優化]
阿新 • • 發佈:2018-11-19
有太多題解在瞎寫,發這個主要是提醒一下不要被傻逼們寫的東西誤導
我好幾次想要把這個題想明白,但那些所謂的“題解”讓我浪費了許多天時間
如果說上面那些題解裡說的“時間”本意是指s[i]而不是轉移過來的位置,那麼原諒我語文不好
二分的是s[i],單調棧裡的元素比較關鍵字也是s[i],而不是位置
#include <bits/stdc++.h> using namespace std; const int MAXN = 1e5 + 6; int a[MAXN], cnt[MAXN], s[MAXN], n, m; long long f[MAXN]; vector<int>q[MAXN]; #define mid ((l+r)>>1) long long Get(int x, int y) {return f[x - 1] + 1ll * a[x] * y * y;} inline int Get_s(int x, int y) {//二分出x比y優的最小的s int l = 1, r = n, ans = 1e9;//x永遠不會比y優的話 ans = inf while (l <= r) { if (Get(x, mid - s[x] + 1) >= Get(y, mid - s[y] + 1)) ans = mid, r = mid - 1; else l = mid + 1; } return ans; } int main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), s[i] = ++cnt[a[i]]; for (int i = 1; i <= n; ++i) { vector<int> &v = q[a[i]]; while (v.size() >= 2 && Get_s(*----v.end(), *--v.end()) <= Get_s(*--v.end(), i)) v.pop_back(); //棧頂下面的元素比棧頂優的s <= 棧頂比 i 優的 s //當棧頂比i優的時候 第二個元素一定比棧頂優 所以棧頂沒有用 可以彈出 v.push_back(i); while (v.size() >= 2 && Get_s(*----v.end(), *--v.end()) <= s[i]) v.pop_back(); //如果第二個元素比棧頂優的最小s<=s[i] 就可以彈出棧頂 f[i] = Get(*--v.end(), s[i] - s[*--v.end()] + 1); } cout << f[n]; return 0; } /* 5 2 2 1 2 3 dp[1] = 2 dp[2] = 8 Get_s(1, 2) = 1 <= s[2](2) s = 1的時候 1就會比2優 -> pop掉2 */