题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1855
题意:最近lxhgww又迷上了投资股票, 通过一段时间的观察和学习,他总结出了股票行情的一些规律。 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每 个i,都有APi>=BPi),但是每天不能无限制地交易,于是股票交易所规定第i天的一次买入至多只能购买ASi股,一次卖出至多只能卖出BSi 股。 另外,股票交易所还制定了两个规定。为了避免大家疯狂交易,股票交易所规定在两次交易(某一天的买入或者卖出均算是一次交易)之间,至少要间隔W天,也就 是说如果在第i天发生了交易,那么从第i+1天到第i+W天,均不能发生交易。同时,为了避免垄断,股票交易所还规定在任何时间,一个人的手里的股票数不 能超过MaxP。 在第1天之前,lxhgww手里有一大笔钱(可以认为钱的数目无限),但是没有任何股票,当然,T天以后,lxhgww想要赚到最多的钱。
思路:设f[i][j]表示到第i天手里持有j的股票的最大收益,那么第i天有三种操作:
对于买入,我们对其变形:
那么可以用单调队列维护f[i-w-1][k]+ap[i]*k(因为对于固定的i,ap[i]是固定的),这样f[i][j]就能做到O(1)计算,而不必枚举k。卖出也一样。
struct node { int x,y; node(){} node(int _x,int _y) { x=_x; y=_y; } }; int f[N][N],n,m,w; node Q[N]; int st,ed; int main() { RD(n,m,w); int ap,bp,as,bs,i,j,k; FOR0(i,n+1) FOR0(j,m+1) f[i][j]=-INF; int ans=0; FOR1(i,n) { RD(ap,bp); RD(as,bs); for(j=0;j<=as;j++) f[i][j]=-ap*j; for(j=0;j<=m;j++) upMax(f[i][j],f[i-1][j]); k=i-w-1; if(k>=0) { st=ed=0; for(j=0;j<=m;j++) { while(st<ed&&Q[st].x<j-as) st++; while(st<ed&&Q[ed-1].y<=f[k][j]+ap*j) ed--; Q[ed++]=node(j,f[k][j]+ap*j); if(st<ed) upMax(f[i][j],Q[st].y-ap*j); } st=ed=0; for(j=m;j>=0;j--) { while(st<ed&&Q[st].x>j+bs) st++; while(st<ed&&Q[ed-1].y<=f[k][j]+bp*j) ed--; Q[ed++]=node(j,f[k][j]+bp*j); if(st<ed) upMax(f[i][j],Q[st].y-bp*j); } } upMax(ans,f[i][0]); } PR(ans); }
BZOJ 1855 股票交易(单调队列优化DP),布布扣,bubuko.com
时间: 2024-10-10 11:14:12