单调栈和单调队列优化dp在本质上是一样的,都是利用单调栈和单调队列这样有特殊功能的数据结构实现对 dp 的优化,其中:
- 单调栈 的功能是找到比当前元素大 / 小的第一个元素(可以理解成距离上最近的元素)
- 单调队列 的功能是维护长度为一个定值的区间内的最大 / 小值
在dp中的具体使用方法就是把前面计算过的dp值存进数据结构中进行维护
单调队列优化dp例题
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 1e5 + 10;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;
void solve()
{
int n, m, k, d;
cin >> n >> m >> k >> d;
vector<vector<int>> g(n + 1, vector<int>(m + 1));
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= m; j ++ )
{
cin >> g[i][j];
}
}
vector<int> ans(n + 1);
for (int i = 1; i <= n; i ++ )
{
vector<int> dp(m + 1);
deque<int> q;
dp[1] = 1;
q.push_back(1);
for (int j = 2; j <= m; j ++ )
{
if (!q.empty() && j - q.front() + 1 > d + 2) q.pop_front();
dp[j] = dp[q.front()] + g[i][j] + 1;
while (!q.empty() && dp[q.back()] >= dp[j]) q.pop_back();
q.push_back(j);
}
ans[i] = dp[m];
}
int res = INF;
for (int i = 1; i + k - 1 <= n; i ++ )
{
int tmp = 0;
for (int j = 0; j < k; j ++ ) tmp += ans[j + i];
res = min(res, tmp);
}
cout << res << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
}