把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P2569 [SCOI2010]股票交易

题面传送门
这道题暴力dp是很好想的。
就是分别从上一天,最晚可转移的天,凭空买来转移。
因为有状态自然叠加所以只要转移最晚可转移的天就好了。
然后会发现这个是可以正反两边单调队列优化的。
复杂度\(O(TP)\)
代码实现:

#include<cstdio>
#include<cstring>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
int n,m,w,x,y,z,f[2039][2039],q[2039],head,tail;
int a[2039],b[2039],c[2039],d[2039];
int main(){
//	freopen("1.in","r",stdin);
	register int i,j;
	scanf("%d%d%d",&n,&m,&w);
	for(i=1;i<=n;i++) scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
	memset(f,-0x3f,sizeof(f));
	for(i=1;i<=n;i++) f[i][0]=0;
	for(i=1;i<=n;i++){
		for(j=1;j<=c[i];j++) f[i][j]=-a[i]*j;
		for(j=0;j<=m;j++) f[i][j]=max(f[i][j],f[i-1][j]);
		if(i<=w+1) continue;
		head=tail=0;
		for(j=0;j<=m;j++){
			while(head!=tail&&q[head+1]+c[i]<j) head++;
			while(head!=tail&&f[i-w-1][q[tail]]-(j-q[tail])*a[i]<=f[i-w-1][j]) tail--;
			q[++tail]=j;
			f[i][j]=max(f[i][j],f[i-w-1][q[head+1]]-(j-q[head+1])*a[i]);
		}
		head=tail=0;
		for(j=m;j>=0;j--){
			while(head!=tail&&q[head+1]>j+d[i]) head++;
			while(head!=tail&&f[i-w-1][q[tail]]+(q[tail]-j)*b[i]<=f[i-w-1][j]) tail--;
			q[++tail]=j;
			f[i][j]=max(f[i][j],f[i-w-1][q[head+1]]+(q[head+1]-j)*b[i]);
		}
	}
	printf("%d\n",f[n][0]);
}
posted @ 2020-10-07 21:53  275307894a  阅读(38)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end