description
solution
考虑动态规划,设f[i][j]表示前i个,用了j个矩阵的最大答案。
f[i][j]=maxk<=if[k][j−1]+a[i]∗(i−k)
,其中a[i]表示第i段的长度。可以发现对于i的两个决策点
x,y(x<y)
,当
(f[y]−f[x])/(y−x)<a[i]
时x是比y更优的。这样就可以维护一个斜率单调递减的单调队列优化动态规划。
code
using namespace std;
int const mn=2*1e4+9;LL inf=1e18+7;
int t,n,K,q[mn];
LL f[mn],g[mn],a[mn];
int main(){
freopen("pyramid.in","r",stdin);
freopen("pyramid.out","w",stdout);
scanf("%d%d",&n,&K);
fo(i,1,n){
int x,y;
scanf("%d%d",&x,&y);
a[i]=y-x+1;
}
fo(i,1,n)f[i]=-inf;
fo(cas,1,K){
int he=0,ti=0;
q[0]=0;
fo(i,1,n){
while((he<ti)&&(f[q[he+1]]-f[q[he]]>a[i]*(q[he+1]-q[he])))he++;
g[i]=f[q[he]]+a[i]*(i-q[he]);
if(i!=n){
while((he<ti)&&((f[q[ti]]-f[q[ti-1]])*(i-q[ti])<(f[i]-f[q[ti]])*(q[ti]-q[ti-1])))ti--;
q[++ti]=i;
}
}
fo(i,0,n)f[i]=g[i];
}
LL ans=0;
fo(i,0,n)ans=max(ans,f[i]);
printf("%lld",ans);
return 0;
}