P5858 黄金圣剑
思路
状态转移方程简单,但是细节较多的单调队列优化dp模板。由于正向遍历队列里含有未知量,因此只能选择倒序遍历来保证队列里都是已知量。有w的限制,每加一次原料需要在队头放入编号w来保证正确性(经验教训),同时处理窗口大小需要谨慎。
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#define maxn 5007
using namespace std;
long long n, w, s, arr[2][maxn], q[maxn], a;
int main(void)
{
ios::sync_with_stdio(false);
cin >> n >> w >> s >> a;
memset(arr, 0x80, sizeof(arr));
int cr = 0; arr[1][1] = a;
for (int i = 2; i <= n; i++, cr ^= 1)
{
cin >> a;
memset(arr[cr], 0x80, sizeof(arr[cr]));
memset(q, 0x80, sizeof(q));
int head = 0, tail = 0;
q[tail++] = w;
for (int j = w; j >= 1; j--)
{
while (head < tail && min(w, j + s - 1) < q[head])
head++;
while (head < tail && arr[cr ^ 1][q[tail - 1]] < arr[cr ^ 1][j - 1])
tail--;
q[tail++] = j - 1;
arr[cr][j] = arr[cr ^ 1][q[head]] + a * j;
}
}
long long ans = INT64_MIN;
for (int i = 1; i <= w; i++)
ans = max(ans, arr[cr ^ 1][i]);
cout << ans << '\n';
return 0;
}

浙公网安备 33010602011771号