参考:https://www.luogu.com.cn/blog/Sooke/solution-p2569
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=2001;
int n,m,w;
int ap,bp,as,bs;
int ans;
int f[N][N] ;// f[i][j] 表示第 i 天后拥有 j 张股票赚的最多钱数
int hh,tt,q[2001];
int main()
{
cin>>n>>m>>w;
memset(f,128,sizeof f); // 128 实际上给 f 数组赋的是 -inf,可以试试看
for(int i=1;i<=n;i++)
{
//买入价格,卖出价格,最多买,最多卖
cin>>ap>>bp>>as>>bs;
for(int j=0;j<=as;j++)
f[i][j]=-1*j*ap; //凭空买
for(int j=0;j<=m;j++)
f[i][j]=max(f[i][j],f[i-1][j]); // 不买也不卖
if(i<=w)//如果小于天数,就不能卖
continue; // 因为第 3,4 种情况都有 i - w - 1,如果 i <= w,会出现负下标
//在之前的基础上买
hh=1,tt=1; // 单调队列准备
for(int j=0;j<=m;j++)
{
while(hh<tt&&q[hh]<j-as)
hh++;
while(hh<tt&&f[i-w-1][q[tt-1]]+q[tt-1]*ap<=f[i-w-1][j]+j*ap)
tt--;
q[tt++]=j;
if(hh<tt)
f[i][j]=max(f[i][j],f[i-w-1][q[hh]]+q[hh]*ap-j*ap);
}
//在之前的基础上卖
hh=1,tt=1;
for(int j=m;j>=0;j--)
{
while(hh<tt&&q[hh]>j+bs)
hh++;
while(hh<tt&&f[i-w-1][q[tt-1]]+q[tt-1]*bp<=f[i-w-1][j]+j*bp)
tt--;
q[tt++]=j;
if(hh<tt)
f[i][j]=max(f[i][j],f[i-w-1][q[hh]]+q[hh]*bp-j*bp);
}
}
for(int i=0;i<=m;i++)
ans=max(ans,f[n][i]);
cout<<ans<<endl;
return 0;
}