P2569 股票交易题解

P2569 股票交易 题解#

思路

容易想到 dp,我们设 fi,j 表示第 i 天剩下 j 张股票最多可以赚到多少钱

显然由于 apbp 所以一天之内不可能既买又卖,只能只买/只卖/不卖不卖

不卖不卖的转移十分容易:

fi,j=fi1,j

而只买分为两种情况:凭空买,在前面交易的基础上买

凭空买的话,转移如下:

fi,j=api×j

在前面交易的基础上买的转移如下:

fi,j=max{fiw1,k(jk)×api}

卖的话只能在前面交易的基础上卖,转移如下:

fi,j=max{fiw1,k+(kj)×bpi}

显然,前两个转移操作是 O(nm) 的,可以接受

而后两个转移则是 O(nm2) 需要优化

对于转移 3 我们可以正序枚举 k,然后搞一个单调队列维护其单调性,以此来转移

因为

fi,j=max{fiw1,k(jk)×api}=(fiw1,k+k×api)j×api

显然 j×api 是一个常数,而前半部分的 fiw1,k+k×api 只跟 k 的取值有关,因此我们可以用单调队列来维护这个东西

这样复杂度就由 O(nm2)O(nm)

可以接受了

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]);//全卖掉最小
}

作者:Into_qwq

出处:https://www.cnblogs.com/into-qwq/p/16531658.html

版权:本作品采用「qwq」许可协议进行许可。

posted @   Into_qwq  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示