E50 单调队列优化DP 股票交易

E50 单调队列优化DP 股票交易_哔哩哔哩_bilibili

 

P2569 [SCOI2010] 股票交易 - 洛谷

// 单调队列 O(T*P)
#include<bits/stdc++.h>
using namespace std;

const int N=2010;
int T,maxP,W;     //天数T,股票最大拥有数maxP,间隔W天
int ap,bp,as,bs;  //买入价ap,卖出价bp,买入数as,卖出数bs
int f[N][N],q[N]; //f[i][j]表示第 i 天后,拥有 j 张股票的最大收益

int main(){
  scanf("%d%d%d",&T,&maxP,&W);
  memset(f,-0x3f,sizeof(f));
  for(int i=1;i<=T;i++){        //枚举天数
    scanf("%d%d%d%d",&ap,&bp,&as,&bs);
    for(int j=0;j<=as;j++) f[i][j]=-ap*j; //凭空买
    for(int j=0;j<=maxP;j++)f[i][j]=max(f[i][j],f[i-1][j]);//不买不卖
    if(i<=W) continue;          //不能转移就跳过
    
    for(int j=0,h=1,t=0; j<=maxP; j++){   //买入(窗口右滑)
      while(h<=t && q[h]<j-as) h++;
      while(h<=t && f[i-W-1][q[t]]+ap*q[t]<=f[i-W-1][j]+ap*j) t--;
      q[++t]=j;
      f[i][j]=max(f[i][j],f[i-W-1][q[h]]-ap*(j-q[h])); 
    }

    for(int j=maxP,h=1,t=0; j>=0; j--){   //卖出(窗口左滑)
      while(h<=t && q[h]>j+bs) h++;
      while(h<=t && f[i-W-1][q[t]]+bp*q[t]<=f[i-W-1][j]+bp*j) t--;
      q[++t]=j;
      f[i][j]=max(f[i][j],f[i-W-1][q[h]]+bp*(q[h]-j));
    } 
  }
  printf("%d",f[T][0]);
}

 

POJ1821 Fence

POJ3017 Cut the Sequence

Luogu P2564 [SCOI2009]生日礼物

Luogu P2219 [HAOI2007]修筑绿化带

Luogu P3957 [NOIP2017 普及组] 跳房子

Luogu P1973 [NOI2011] NOI 嘉年华

Luogu P3229 [HNOI2013]旅行

 

posted @ 2023-04-29 14:20  董晓  阅读(421)  评论(0)    收藏  举报