只WA了一个点,非常痛苦
单调队列确实写丑了,但是不知道应该怎么改,求大佬帮助。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
char getch()
{
static char buf[1 << 14], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 14, stdin), p1 == p2) ? EOF : *p1++;
}
void read(ll &x)
{
x = 0;
char c = getch(), last = ' ';
while(c < '0' || c > '9')
{
last = c;
c = getch();
}
while(c >= '0' && c <= '9')
{
x = x * 10 + (c - '0');
c = getch();
}
if(last == '-') x = -x;
}
ll n, w, s, st, en;
ll a[6000];
ll dp[5501][5501];
pair<ll, ll> que[5501];
int main()
{
freopen("P5858_20.in", "r", stdin);
read(n); read(w); read(s);
for(ll i = 1; i <= n; ++i) read(a[i]);
for(ll i = 1; i <= n; ++i)
{
dp[i][0] = -1e18;
ll h = min(i, w);
for(ll j = 1; j <= h; ++j)
dp[i][j] = dp[i - 1][j - 1] + j * a[i];
if(i >= w) dp[i][w] = max(dp[i][w], dp[i - 1][w] + w * a[i]);
//单调队列
st = en = 1;
for(ll j = 0; j <= h; ++j) que[j].first = que[j].second = -1e18;
//先将 0 ~ s 压入队列
for(ll j = 0; j <= min(h, s); ++j)
{
while(dp[i][j] > que[en].second && en >= st) en--;
que[++en].first = j;
que[en].second = dp[i][j];
}
dp[i][0] = que[st].second;
//每次先判断队头的数是否符合位置要求,再将队头赋给 f[i][j]
for(ll j = 1; j <= h; ++j)
{
if(j + s <= h)
{
while(dp[i][j + s] > que[en].second && en >= st) en--;
que[++en].first = j + s;
que[en].second = dp[i][j + s];
}
if(j > que[st].first) st++;
dp[i][j] = que[st].second;
}
}
ll maxn = -1e18;
for(ll i = 1; i <= w; ++i) maxn = max(maxn, dp[n][i]);
printf("%lld", maxn);
return 0;
}