单调队列求差错QAQ
查看原帖
单调队列求差错QAQ
105820
阿尔托莉雅丶楼主2022/3/25 15:30

RT 这是下面是没用单调队列的呆毛

没有T的点都过了,正确性应该是能保证的

#include <iostream>
#include <algorithm>
#include <math.h>
#include <vector>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int N = 2e3 + 5;   //remember to modify the range of the data!!
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

int n, m, T;
ll f[N][N]; //第i天持有j支股票的最大收益
int ap[N], bp[N], as[N], bs[N];
ll mx[N][N];//前i天中,持有j支股票的最大收益
int main(void)
{
    int t, mp, w;
    cin >> n >> mp >> w;

    for(int i = 1; i <= n; i++)
        cin >> ap[i] >> bp[i] >> as[i] >> bs[i];
    memset(f, -0x3f, sizeof(f));
    memset(mx, -0x3f, sizeof(mx));
    mx[0][0] = 0;
    f[0][0] = 0;
    for(int i = 1; i <= n; i++)
    {
        for(int j = 0; j <= mp; j++)
        {
            f[i][j] = f[i - 1][j];
            for(int k = 1; k <= min(j, as[i]); k++)
            {
                int pre = max(i - w - 1, 0);
                f[i][j] = max(f[i][j] , mx[pre][j - k] - ap[i] * k);
            }
            for(int k = 1; k <= min(bs[i], mp - j); k++)
            {
                int pre = max(i - w - 1, 0);
                f[i][j] = max(f[i][j], mx[pre][j + k] + bp[i] * k);
            }
            mx[i][j] = max(mx[i - 1][j], f[i][j]);
        }
    }
    cout << f[n][0];
    return 0;
}

然后使用单调队列优化后

wa了

#include <iostream>
#include <algorithm>
#include <math.h>
#include <vector>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int N = 2e3 + 5;   //remember to modify the range of the data!!
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

int n, m, T;
ll f[N][N];
int ap[N], bp[N], as[N], bs[N];
ll mx[N][N];//所有前i天中,持有j支股票的最大收益
int main(void)
{
    int t, mp, w;
    cin >> n >> mp >> w;

    for(int i = 1; i <= n; i++)
    {
        // cin >> ap[i] >> bp[i] >> as[i] >> bs[i];
        scanf("%d%d%d%d", ap + i, bp + i, as + i, bs + i);
    }
    memset(f, -0x3f, sizeof(f));
    memset(mx, -0x3f, sizeof(mx));
    mx[0][0] = 0;
    f[0][0] = 0;
    deque <pair <ll, int> > q1, q2;
    for(int i = 1; i <= n; i++)
    {
        q1.clear();
        q2.clear();
        for(int j = 0; j <= mp; j++)
        {
            f[i][j] = f[i - 1][j]; //不买不卖
            
            int pre = max(i - w - 1, 0); //进行交易时从前面那一天转移
            int up = j - 1, low = j - min(j ,as[i]); // low, up表示上下界,单调队列在这个区间找最值
            //买
            if(up >= 0)  
            {
                while(!q1.empty() && q1.back().first <= mx[pre][up])
                    q1.pop_back();
                q1.push_back({mx[pre][up], up});
                while(!q1.empty() && q1.front().second < low)
                    q1.pop_front();

                f[i][j] = max(f[i][j] , q1.front().first - ap[i] * (j - q1.front().second));
            }
            //卖
            up = min(j + bs[i], mp), low = j + 1;
            if(j == 0) //第一次先把区间全装进去,后面的只需要每次判一个就行了
            {
                for(int k = low; k <= up; k++)
                {
                    while(!q2.empty() && q2.back().first <= mx[pre][k])
                        q2.pop_back();
                    q2.push_back({mx[pre][k], k});
                    while(!q2.empty() && q2.front().second < low)
                        q2.pop_front();
                }
            }
            if(low <= mp)
            {
                while(!q2.empty() && q2.back().first <= mx[pre][up])
                    q2.pop_back();
                q2.push_back({mx[pre][up], up});
                while(!q2.empty() && q2.front().second < low)
                    q2.pop_front();
                f[i][j] = max(f[i][j], q2.front().first + bp[i] * (q2.front().second - j));
            }

            mx[i][j] = max(mx[i - 1][j], f[i][j]);
        }
    }

    cout << f[n][0];

    return 0;
}

2022/3/25 15:30
加载中...