1. 程式人生 > >Codeforces Round #521 (Div. 3): F. Pictures with Kittens(DP+單調佇列)

Codeforces Round #521 (Div. 3): F. Pictures with Kittens(DP+單調佇列)

 

題意:

你有n幅畫,第i幅畫的好看程度為ai,再給你兩個數字k,x,表示你要從中選出剛好x幅畫,並且相鄰兩幅畫的距離不能≥k,好看程度之和最大能多少,選不出來輸出-1,F1資料範圍<200,F2資料範圍<5000

注意相鄰兩幅畫的距離不能≥k指的是中間沒有選的畫個數不能≥k,而不是絕對值之差≥k

 

思路:

dp[x][y]表示只考慮前y幅畫,第y幅必選,且總共選了x幅畫的最大好看程度

轉移:dp[x][y] = max(dp[x-1][y-k]~dp[x-1][y-1])+a[y]

然後這個DP很明顯可以用單調佇列維護

 

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 1000000007
LL a[5005], dp[2][5005];
int st[5005];
int main(void)
{
	LL ans;
	int n, k, m, i, p, R, L, now;
	scanf("%d%d%d", &n, &m, &k);
	for(i=1;i<=n;i++)
		scanf("%lld", &a[i]);
	memset(dp, -62, sizeof(dp));
	dp[0][0] = 0, now = 1;
	for(p=1;p<=k;p++)
	{
		L = 1, R = 0;
		st[++R] = 0;
		for(i=1;i<=n;i++)
		{
			while(R>=L && st[L]+m<i)
				L++;
			dp[now][i] = dp[now^1][st[L]]+a[i];
			while(R>=L && dp[now^1][st[R]]<=dp[now^1][i])
				R--;
			st[++R] = i;
		}
		now ^= 1;
	}
	now ^= 1, ans = -1;
	for(i=n;i>=n-m+1;i--)
		ans = max(ans, dp[now][i]);
	printf("%lld\n", ans);
	return 0;
}