P2569 [SCOI2010]股票交易
SOL
设
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示第
i
i
i天持有
j
j
j股的最大收益
30
p
t
s
30pts
30pts:朴素转移
O
(
n
4
)
O(n^4)
O(n4)
不买卖:
d
p
[
i
]
[
j
]
=
d
p
[
i
−
1
]
[
j
]
dp[i][j]=dp[i-1][j]
dp[i][j]=dp[i−1][j]
买:如果是第一次买:
d
p
[
i
]
[
j
]
=
−
j
∗
a
p
[
i
]
(
0
<
=
j
<
=
a
s
[
i
]
)
dp[i][j]=-j*ap[i](0<=j<=as[i])
dp[i][j]=−j∗ap[i](0<=j<=as[i])
否则:
d
p
[
i
]
[
j
]
=
d
p
[
i
−
k
]
[
j
−
t
]
−
t
∗
a
p
[
i
]
(
k
>
=
m
a
x
(
i
−
w
−
1
,
0
)
,
0
<
=
t
<
=
a
s
[
i
]
)
dp[i][j]=dp[i-k][j-t]-t*ap[i](k>=max(i-w-1,0),0<=t<=as[i])
dp[i][j]=dp[i−k][j−t]−t∗ap[i](k>=max(i−w−1,0),0<=t<=as[i])
卖:
d
p
[
i
]
[
j
]
=
d
p
[
i
−
k
]
[
j
+
t
]
+
t
∗
b
p
[
i
]
(
k
>
=
m
a
x
(
i
−
w
−
1
,
0
)
,
0
<
=
t
<
=
b
s
[
i
]
)
dp[i][j]=dp[i-k][j+t]+t*bp[i](k>=max(i-w-1,0),0<=t<=bs[i])
dp[i][j]=dp[i−k][j+t]+t∗bp[i](k>=max(i−w−1,0),0<=t<=bs[i])
上述三者取
M
a
x
Max
Max
50
p
t
s
50pts
50pts:
O
(
n
3
)
O(n^3)
O(n3)
考虑到有些天可以选择不买,于是
i
i
i直接由
i
−
w
−
1
i-w-1
i−w−1转移过来即可
100
p
t
s
100pts
100pts:
O
(
n
2
)
O(n^2)
O(n2)
考虑到会取
m
a
x
max
max,自然想到用单调队列优化
买:
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
−
w
−
1
]
[
j
−
t
]
−
t
∗
a
p
[
i
]
)
(
0
<
=
t
<
=
a
s
[
i
]
)
dp[i][j]=max(dp[i-w-1][j-t]-t*ap[i])(0<=t<=as[i])
dp[i][j]=max(dp[i−w−1][j−t]−t∗ap[i])(0<=t<=as[i])
令
k
=
j
−
t
k=j-t
k=j−t
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
−
w
−
1
]
[
k
]
−
(
j
−
k
)
∗
a
p
[
i
]
)
=
m
a
x
(
d
p
[
i
−
w
−
1
]
[
k
]
+
k
∗
a
p
[
i
]
)
−
j
∗
a
p
[
i
]
dp[i][j]=max(dp[i-w-1][k]-(j-k)*ap[i])=max(dp[i-w-1][k]+k*ap[i])-j*ap[i]
dp[i][j]=max(dp[i−w−1][k]−(j−k)∗ap[i])=max(dp[i−w−1][k]+k∗ap[i])−j∗ap[i]
卖:
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
−
w
−
1
]
[
j
+
t
]
+
t
∗
b
p
[
i
]
0
(
0
<
=
t
<
=
b
s
[
i
]
)
dp[i][j]=max(dp[i-w-1][j+t]+t*bp[i]0(0<=t<=bs[i])
dp[i][j]=max(dp[i−w−1][j+t]+t∗bp[i]0(0<=t<=bs[i])
令
k
=
j
+
t
k=j+t
k=j+t
d
p
[
i
]
[
j
]
=
m
a
x
(
d
p
[
i
−
w
−
1
]
[
k
]
+
(
k
−
j
)
∗
b
p
[
i
]
)
=
m
a
x
(
d
p
[
i
−
w
−
1
]
[
k
]
+
k
∗
b
p
[
i
]
)
−
j
∗
b
p
[
i
]
dp[i][j]=max(dp[i-w-1][k]+(k-j)*bp[i])=max(dp[i-w-1][k]+k*bp[i])-j*bp[i]
dp[i][j]=max(dp[i−w−1][k]+(k−j)∗bp[i])=max(dp[i−w−1][k]+k∗bp[i])−j∗bp[i]
代码:
#include<bits/stdc++.h>
using namespace std;
#define re register
inline char nc(){
static char buf[10000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,10000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd(){
int re data=0;static char ch=0;ch=nc();
while(!isdigit(ch))ch=nc();
while(isdigit(ch))data=(data<<1)+(data<<3)+(ch^48),ch=nc();
return data;
}
template<typename T>inline void chmax(T &a,T b){return a>b?a:b;}
const int N=2005;
int ap[N],bp[N],dp[N][N],ans,as[N],bs[N],q[N],l,r,t,w,m;
signed main(){
t=rd(),m=rd(),w=rd();
for(int re i=1;i<=t;++i)ap[i]=rd(),bp[i]=rd(),as[i]=rd(),bs[i]=rd();
memset(dp,0xb3,sizeof(dp)),dp[0][0]=0;
for(int re i=1;i<=t;++i){
for(int re j=0;j<=as[i];++j)dp[i][j]=-j*ap[i];
for(int re j=0;j<=m;++j)dp[i][j]=max(dp[i][j],dp[i-1][j]);
if(i<=w+1)continue;
l=1,r=0;
for(int re j=0;j<=m;++j){
int re k=i-w-1;
while(l<=r&&q[l]<j-as[i])++l;
while(l<=r&&dp[k][j]+j*ap[i]>dp[k][q[r]]+q[r]*ap[i])--r;
q[++r]=j,dp[i][j]=max(dp[i][j],dp[k][q[l]]-ap[i]*(j-q[l]));
}
l=1,r=0;
for(int re j=m;j>=0;--j){
int re k=i-w-1;
while(l<=r&&q[l]>j+bs[i])++l;
while(l<=r&&dp[k][j]+j*bp[i]>dp[k][q[r]]+q[r]*bp[i])--r;
q[++r]=j,dp[i][j]=max(dp[i][j],dp[k][q[l]]+bp[i]*(q[l]-j));
}
}
for(int re j=0;j<=m;++j)ans=max(ans,dp[t][j]);
printf("%d",ans);
return 0;
}