簡單的單調隊列優化 DPc++
處理略微有點噁心,因而乎,用來取 \(\max\) 的極小值直接開到了 long long
的最小極限,了 define int long long
/cygit
必須按編號順序加材料,明顯的階段性,且數據範圍明顯地提示咱們能夠 DP算法
狀態也很好想,設 \(f_{i, j}\) 表示放完前 \(i\) 個物品後鍋內有 \(j\) 個物品時的最大答案。數組
那麼使用填表法轉移:優化
那麼發現 \(k\) 的取值範圍隨着 \(j\) 的變化恰好是個滑動窗口,其他的項都是輸入時或枚舉過程當中的定值,所以使用單調隊列優化取最大值的操做。spa
另外表示階段的 \(i\) 只會取到上一個階段的答案,所以開滾動數組壓掉第一維。code
建議把可能須要開 long long
的都打開,若是不以爲很傻或者比較懶的話也能夠直接 define int long long
。隊列
內層循環能夠倒序枚舉,這樣就只須要一開始的時候往單調隊列裏壓一個元素。不用亂七八糟的處理。ip
初始化極小值的時候要足夠小親測 \(-10^{12}\) 都不夠用,還不能在加上一些負值以後爆 long long
的最小範圍。get
/* By chen_green 2020/11/5 設 f[i][j]表示放完前 i 件物品後鍋中已經放了 j 件物品的最大耐久度 f[i][j] = max{f[i - 1][k]} + j * a[i] (j - 1 <= k <= j - 1 + s) 滾動數組 + 單調隊列優化 */ #include <bits/stdc++.h> #define int long long #define LL long long using namespace std; inline int read0() { int fh = 1, w = 0; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') fh = -1; for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0'); return fh * w; } inline LL read() { LL fh = 1, w = 0; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') fh = -1; for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0'); return fh * w; } const int Maxn = 5505; LL f[2][Maxn]; LL a[Maxn]; int n, w, s; deque<LL> dq; void initdq() {while(!dq.empty()) dq.pop_back();} void push(int x) { if((int)dq.size() >= (int)(s + 1)) dq.pop_front(); while((!dq.empty()) && (dq.back() <= x)) dq.pop_back(); dq.push_back(x); } LL Getmax() { return dq.front(); } signed main() { n = read0(); w = read0(); s = read0(); for(register int i = 1; i <= n; ++i) { a[i] = read(); } for(register int i = 0; i <= w; ++i) f[0][i] = f[1][i] = -9223372036854775808 / 2; LL f0 = f[0][0]; f[0][0] = 0; LL ans = -9223372036854775808; for(register int i = 1; i <= n; ++i) { if(i == 2) f[0][0] = f0; initdq(); push(f[i - 1 & 1][w]); for(register int j = w; j >= 1; --j) { push(f[i - 1 & 1][j - 1]); f[i & 1][j] = Getmax() + j * a[i]; //cout << f[i & 1][j] << " "; } } for(int i = 1; i <= w; ++i) { ans = max(ans, f[n & 1][i]); } printf("%lld", ans); }