P2569 股票交易题解
P2569 股票交易 题解#
思路:
容易想到 ,我们设 表示第 天剩下 张股票最多可以赚到多少钱
显然由于 所以一天之内不可能既买又卖,只能只买/只卖/不卖不卖
不卖不卖的转移十分容易:
而只买分为两种情况:凭空买,在前面交易的基础上买
凭空买的话,转移如下:
在前面交易的基础上买的转移如下:
卖的话只能在前面交易的基础上卖,转移如下:
显然,前两个转移操作是 的,可以接受
而后两个转移则是 需要优化
对于转移 我们可以正序枚举 ,然后搞一个单调队列维护其单调性,以此来转移
因为
显然 是一个常数,而前半部分的 只跟 的取值有关,因此我们可以用单调队列来维护这个东西
这样复杂度就由
可以接受了
code:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2e3+5;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int f[N][N],q[N];
signed main(){
int n=read(),m=read(),w=read();
memset(f,0xcf,sizeof(f));//初始赚的钱为无穷小
for(int i=1;i<=n;++i){
int ap=read(),bp=read(),as=read(),bs=read();
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;
int l=1,r=0;
for(int j=0;j<=m;++j){
while(l<=r&&q[l]<j-as) ++l;
while(l<=r&&f[i-w-1][q[r]]+q[r]*ap<=f[i-w-1][j]+j*ap) --r;
q[++r]=j;
if(l<=r)
f[i][j]=max(f[i][j],f[i-w-1][q[l]]+q[l]*ap-j*ap);
}
l=1,r=0;
for(int j=m;j>=0;--j){
while(l<=r&&q[l]>j+bs) ++l;
while(l<=r&&f[i-w-1][q[r]]+q[r]*bp<=f[i-w-1][j]+j*bp) --r;
q[++r]=j;
if(l<=r)
f[i][j]=max(f[i][j],f[i-w-1][q[l]]+q[l]*bp-j*bp);
}
}
printf("%d",f[n][0]);//全卖掉最小
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现