https://vjudge.net/solution/2611950 上师兄的代码。。
这个地方的维护的是单调递减的队列,,
这样
买进: f[i][j]=max(f[i-W-1][k]-(j-k)*e[i].ap,f[i][j])。在这里j-e[i].as
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<queue>
#include<cstring>
using namespace std;
#define sf scanf
#define pf printf
#define mem(a,b) memset(a,b,sizeof(a));
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define M 200020
#define mod 998244353
#define ULL unsigned long long
#define LL long long
#define inf 0x3f3f3f3f
#define ls (rt<<1)
#define rs (ls|1)
#define md ((ll+rr)>>1)
#define mxn 2020
//2017年08月09日08:09:06 10min
//2017年08月09日08:25:16 10min
int dp[mxn][mxn];
int ap[mxn],bp[mxn],as[mxn],bs[mxn];
int t,P,w;
void read(){
sf("%d%d%d",&t,&P,&w);
rep(i,1,t)sf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]);
rep(i,0,t)rep(j,0,P)dp[i][j]=-inf;
}
int main(){
freopen("in.txt","r",stdin);
int T ;sf("%d",&T);
while(T--){
read();
for(int i=1;i<=t;++i){
for(int j=0;j<=P;++j)
dp[i][j]=max(dp[i-1][j],dp[i][j]);
if(i<=w+1){
for(int j=0;j<=min(as[i],P);++j)
dp[i][j]=max(dp[i][j],-j*as[i]);
continue;
}
int u=i-w-1;
deque<int>q;
for(int j=0;j<=P;++j){
while(!q.empty()&&dp[u][q.back()]+q.back()*ap[i]<dp[u][j]+j*ap[i])q.pop_back();
q.push_back(j);
while(!q.empty()&&q.front()+as[i]<j)q.pop_front();
if(!q.empty())
dp[i][j]=max(dp[i][j],dp[u][q.front()]-(j-q.front())*ap[i]);
}
while(!q.empty())q.pop_front();
for(int j=P;j>=0;--j){
while(!q.empty()&&dp[u][q.back()]+q.back()*bp[i]<dp[u][j]+j*bp[i])q.pop_back();
q.push_back(j);
while(!q.empty()&&q.front()-bs[i]>j)q.pop_front();
if(!q.empty())
dp[i][j]=max(dp[i][j],dp[u][q.front()]+(q.front()-j)*bp[i]);
}
}
int ans=0;
rep(i,0,P)ans=max(ans,dp[t][i]);
pf("%d\n",ans);
}
}