JZOJ 5347. 【NOIP2017提高A组模拟9.5】遥远的金字塔

题目

分析

毫无疑问 \(dp\)
\(f_{i,j}\) 表示选到第 \(i\) 层,已选 \(j\) 个矩阵最大覆盖面积
那么 \(f_{i,j}=\max{f_{l,j}+w_i*(i-l)}\)
显然斜率优化

\(Code\)

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long LL;

int n , k , q[20005];
LL f[20005][105];
struct node{
	int x , y , w;
}p[20005];

double slope(int j , int l , int r)
{
	return 1.0 * (f[l][j] - f[r][j]) / (l - r);
}

int main()
{
	freopen("pyramid.in" , "r" , stdin);
	freopen("pyramid.out" , "w" , stdout);
	scanf("%d%d" , &n , &k);
	for(register int i = 1; i <= n; i++) 
		scanf("%d%d" , &p[i].x , &p[i].y) , p[i].w = p[i].y - p[i].x + 1;
	int h , t;
	for(register int j = 1; j <= k; j++)
	{
		h = t = 1;
		for(register int i = 1; i <= n; i++)
		{
			while (h < t && slope(j - 1 , q[h + 1] , q[h]) > p[i].w) h++;
			f[i][j] = f[q[h]][j - 1] + 1LL * p[i].w * (i - q[h]);
			while (h <= t && slope(j - 1 , q[t] , q[t - 1]) < slope(j - 1 , i , q[t])) t--;
			q[++t] = i;
		}
	}
	LL ans = 0;
	for(register int i = 1; i <= n; i++) ans = max(ans , f[i][k]);
	printf("%lld" , ans);
} 
posted @ 2020-10-09 09:34  leiyuanze  阅读(101)  评论(0编辑  收藏  举报