【BZOJ】【1855】【SCOI2010】/【HDOJ】【3401】股票交易
DP/单调队列优化
题解:http://www.cnblogs.com/jianglangcaijin/p/3799736.html
令f[i][j]表示第 i 天结束后,手里剩下 j 股的最大利润,则有:
\[ f[i][j]= \begin{cases} f[i-1][j] & &{(不买不卖)}\\ f[i-w-1][k]-ap[i]*(j-k)& &{ j-as[i] \leq k \leq j-1 (买入)}\\ f[i-w-1][k]+bp[i]*(k-j)& &{ j+1 \leq k \leq j+bs[i] (卖出)} \end{cases} \]
对于买入,我们将式子变形得到:
$$ f[i][j]=f[i-w-1][k]+ap[i]*k-ap[i]*j $$
我们知道单调队列优化可以将形如 $ f[i]=max/min \{ f[k] \}+g[i] $ 的式子中对k的枚举利用队列进行优化,这个式子中,"f[k]" 即是 $ f[i-w-1][k]+ap[i]*k $,“g[i]”即是 $ -ap[i]*j $,所以我们在枚举 j 的同时即可完成对k的维护(即每个f[i]都是一次单调队列优化下的DP)
而卖出同理。
1 /************************************************************** 2 Problem: 1855 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:380 ms 7 Memory:17068 kb 8 ****************************************************************/ 9 10 //BZOJ 1855 11 #include<cmath> 12 #include<vector> 13 #include<cstdio> 14 #include<cstring> 15 #include<cstdlib> 16 #include<iostream> 17 #include<algorithm> 18 #define rep(i,n) for(int i=0;i<n;++i) 19 #define F(i,j,n) for(int i=j;i<=n;++i) 20 #define D(i,j,n) for(int i=j;i>=n;--i) 21 #define pb push_back 22 using namespace std; 23 int getint(){ 24 int v=0,sign=1; char ch=getchar(); 25 while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();} 26 while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();} 27 return v*=sign; 28 } 29 const int N=2010,INF=~0u>>2; 30 typedef long long LL; 31 /******************tamplate*********************/ 32 33 struct node{ 34 int x,y; 35 node(int _=0,int __=0):x(_),y(__){} 36 }q[N]; 37 int f[N][N]; 38 int main(){ 39 #ifndef ONLINE_JUDGE 40 freopen("1855.in","r",stdin); 41 freopen("1855.out","w",stdout); 42 #endif 43 int n=getint(),m=getint(),w=getint(); 44 F(i,0,n) F(j,0,m) f[i][j]=-INF; 45 int ans=0,ap,bp,as,bs; 46 F(i,1,n){ 47 ap=getint(); bp=getint(); as=getint(); bs=getint(); 48 F(j,0,as) f[i][j]=-ap*j; 49 F(j,0,m) f[i][j]=max(f[i][j],f[i-1][j]); 50 int k=i-w-1; 51 if (k>=0){ 52 int st=0,ed=0; 53 F(j,0,m){ 54 while(st<ed && q[st].x<j-as) st++; 55 while(st<ed && q[ed-1].y<=f[k][j]+ap*j) ed--; 56 q[ed++]=node(j,f[k][j]+ap*j); 57 if (st<ed) f[i][j]=max(f[i][j],q[st].y-ap*j); 58 } 59 st=ed=0; 60 D(j,m,0){ 61 while(st<ed && q[st].x>j+bs) st++; 62 while(st<ed && q[ed-1].y<=f[k][j]+bp*j) ed--; 63 q[ed++]=node(j,f[k][j]+bp*j); 64 if (st<ed) f[i][j]=max(f[i][j],q[st].y-bp*j); 65 } 66 } 67 ans=max(ans,f[i][0]); 68 } 69 printf("%d\n",ans); 70 return 0; 71 }