85求助
查看原帖
85求助
53164
WorldBest丶牛顿楼主2020/10/21 16:15

WAWA了一个点,非常痛苦
单调队列确实写丑了,但是不知道应该怎么改,求大佬帮助。

#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;
}

2020/10/21 16:15
加载中...