Description
Input
Output
Sample Input
5 3 1 6 1 5 3 5 4 4 4 4
Sample Output
15
Data Constraint
Hint
Summary
设f[i][j]表示前i个,用了j个矩阵的最大答案。
f[i][j]=maxf[k][j−1]+a[i]∗(i−k)
其中a[i]表示第i段的长度。可以发现对于i的两个决策点x,y(x<y)x,y(x<y),当(f[y]−f[x])/(y−x)<a[i](f[y]−f[x])/(y−x)<a[i]时x是比y更优的。
这样就可以维护一个斜率单调递减的单调队列优化动态规划。
1 #include<cstdio> 2 #define N 50007 3 using namespace std; 4 long long f[N][107]; 5 int w[N],d[N],n,m; 6 double js(int x,int y,int z){ 7 return (double)(f[x][z]-f[y][z])/(double)(x-y); 8 } 9 long long max(long long x,long long y){ 10 if (x>y) return x; 11 return y; 12 } 13 int main() 14 { 15 int x,y,l,r; 16 long long ans=0; 17 scanf("%d%d",&n,&m); 18 for (int i=1;i<=n;i++){ 19 scanf("%d%d",&x,&y); 20 w[i]=y-x+1; 21 } 22 for (int i=1;i<=m;i++){ 23 l=r=0; 24 for (int j=1;j<=n;j++){ 25 while (l<r&&js(d[l],d[l+1],i-1)>w[j]) l++; 26 while (l<r&&js(d[r-1],d[r],i-1)<js(d[r],j,i-1)) r--; 27 long long k=(j-d[l]); 28 f[j][i]=max(f[j-1][i],f[d[l]][i-1]+k*w[j]); 29 ans=max(f[j][i],ans); 30 d[++r]=j; 31 } 32 } 33 printf("%lld",ans); 34 }