单调队列 20pts 求助
查看原帖
单调队列 20pts 求助
688783
SilverLi楼主2024/4/5 15:46
#include <bits/stdc++.h>
#define int long long
using namespace std;
inline int read()
{
    int ans = 0, f = 0;
    char c = getchar();
    while (!isdigit(c))
        f |= (c == '-'), c = getchar();
    while (isdigit(c))
        ans = (ans << 3) + (ans << 1) + c - 48, c = getchar();
    return f ? -ans : ans;
}
void write(int x)
{
    if (x < 0)
        putchar('-'), x = -x;
    if (x > 9)
        write(x / 10);
    putchar(x % 10 + 48);
}
const int N = 2e3 + 5;
int n, maxp, w, cnta, cntb;
int ap[N], bp[N], as[N], bs[N];
int f[N][N], last[N];
struct que
{
    int h, t, q[N], id[N];
    inline void init() { h = 1, t = 0; }
    inline void updata(int goal)
    {
        while (h <= t && id[h] < goal)
            ++h;
    }
    inline void insert(int x, int i, int goal)
    {
        while (h <= t && id[h] < goal)
            ++h;
        while (h <= t && q[t] < x)
            --t;
        q[++t] = x, id[t] = i;
    }
    inline int max()
    {
        if (h > t)
            return -0x3f3f3f3f;
        return q[h];
    }
} a, b;
signed main()
{
    // freopen(".silver_in", "r", stdin);
    // freopen(".silver_out", "w", stdout);
    n = read(), maxp = read(), w = read();
    for (int i = 1; i <= n; ++i)
        ap[i] = read(), bp[i] = read(), as[i] = read(), bs[i] = read();
    memset(f, -0x3f, sizeof f), memset(last, -0x3f, sizeof last);
    f[0][0] = last[0] = 0;
    for (int i = 1; i <= n; ++i)
    {
        a.init(), b.init(), cnta = cntb = 0;
        for (int j = 0; j <= maxp; ++j)
        {
            f[i][j] = last[j];
            if (j <= as[i])
                f[i][j] = max(f[i][j], -j * ap[i]);
            if (i - w - 1 >= 1)
            {
                int k = i - w - 1, fir = max(j - as[i], 0ll), end = min(j + bs[i], maxp);
                while (cnta <= j - 1)
                    a.insert(f[k][cnta] - (j - cnta) * ap[i], cnta, fir), ++cnta;
                while (cntb <= end)
                    b.insert(f[k][cntb] + (cntb - j) * bp[i], cntb, j + 1), ++cntb;
                a.updata(fir), b.updata(j + 1);
                f[i][j] = max(f[i][j], max(a.max(), b.max()));
            }
            last[j] = max(last[j], f[i][j]);
            // cerr << i << ' ' << j << ' ' << f[i][j] << endl;
        }
    }
    int ans = 0;
    for (int j = 0; j <= maxp; ++j)
        ans = max(ans, f[n][j]);
    write(ans);
    return 0;
}
2024/4/5 15:46
加载中...