【题解】Luogu P2569 [SCOI2010] 股票交易 单调队列+dp
状态转移:
设$f[i][j]$为第$i$天一共有$j$张股票
1. 不卖也不买 $f[i][j]=max(f[i][j],f[i-1][j])$
2. 买入 $f[i][j]=max(f[i][j],f[i-w-1][j+k]-k*bp[i])$
3. 卖出 $f[i][j]=max(f[i][j],f[i-w-1][j-k]+k*ap[i]$
4. 第一次买 $f[i][j]=-j*ap[i]$
复杂度$n^3$会 T,需要优化
单调队列,对于3,入队时把股票转成资产,维护最大资产,出队时再换成相应股票
2同理
code
1 #include <bits/stdc++.h> 2 using namespace std; 3 namespace gengyf{ 4 #define int long long 5 //const int maxn=5e4+10; 6 const int mod=1e9; 7 inline int read(){ 8 int f=1,x=0;char s=getchar(); 9 while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} 10 while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} 11 return f*x; 12 } 13 int n,w,maxp,ap[2010],bp[2010],as[2010],bs[2010]; 14 int f[2010][2010],q[2010],l=1,r=0,ans; 15 int main(){ 16 n=read();maxp=read();w=read(); 17 for(int i=1;i<=n;i++){ 18 ap[i]=read();bp[i]=read();as[i]=read();bs[i]=read(); 19 } 20 memset(f,-0x7f,sizeof(f)); 21 for(int i=0;i<=n;i++)f[i][0]=0; 22 for(int i=1;i<=n;i++){ 23 for(int j=0;j<=as[i];j++){ 24 f[i][j]=-j*ap[i]; 25 } 26 for(int j=maxp;j>=0;j--){ 27 f[i][j]=max(f[i][j],f[i-1][j]); 28 } 29 if(i-w-1<0)continue; 30 l=1;r=0; 31 for(int j=0;j<=maxp;j++){ 32 while(l<=r&&q[l]<j-as[i]) l++; 33 while(l<=r&&f[i-w-1][j]+ap[i]*j>=f[i-w-1][q[r]]+ap[i]*q[r]) r--; 34 q[++r]=j; 35 if(l<=r) f[i][j]=max(f[i][j],f[i-w-1][q[l]]-ap[i]*(j-q[l])); 36 } 37 l=1;r=0; 38 for(int j=maxp;j>=0;j--){ 39 while(l<=r&&q[l]>j+bs[i]) l++; 40 while(l<=r&&f[i-w-1][j]+bp[i]*j>=f[i-w-1][q[r]]+bp[i]*q[r]) r--; 41 q[++r]=j; 42 if(l<=r) f[i][j]=max(f[i][j],f[i-w-1][q[l]]+bp[i]*(q[l]-j)); 43 } 44 } 45 ans=0; 46 for(int i=0;i<=maxp;i++){ 47 ans=max(ans,f[n][i]); 48 } 49 printf("%lld",ans); 50 return 0; 51 } 52 } 53 signed main(){ 54 gengyf::main(); 55 return 0; 56 }