卧薪尝胆,厚积薄发。
USACO2011OPEN GOLD 修剪草坪
Date: Sun Oct 21 11:11:01 CST 2018
In Category:
NoCategory
Description:
给
$n$
个数,求一个权值和最大的子序列满足任意一段长度都不超过
$k$
。
$1\leqslant n\leqslant 10^5$
Solution:
肯定是
$DP$
,方程为
$f[i]=\max(f[j-1]+sum[i]-sum[j])(i-j\leqslant k)$
,化一下就是
$f[i]=sum[i]+\max(f[j-1]-sum[j])(i-k\leqslant j<i)$
,于是这是一个滑动窗口区间极值可以用单调队列。
Code:
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
int n,k;
#define MAXN 100010
typedef long long ll;
ll a[MAXN],sum[MAXN];
int q[MAXN],head,tail;
ll F[MAXN],*f = F + 1;
int main()
{
scanf("%d%d",&n,&k);
for(int i = 1;i <= n;++i)scanf("%d",&a[i]);
for(int i = 1;i <= n;++i)sum[i] = sum[i - 1] + a[i];
head = 1;tail = 0;q[++tail] = 0;
ll ans = 0;
for(int i = 1;i <= n;++i)
{
while(head <= tail && q[head] < i - k)++head;
f[i] = f[q[head] - 1] + sum[i] - sum[q[head]];
while(head <= tail && f[q[tail] - 1] - sum[q[tail]] <= f[i - 1] - sum[i])--tail;
q[++tail] = i;
ans = max(ans,f[i]);
}
cout << ans << endl;
return 0;
}
In tag:
DP-单调队列优化DP
Copyright © 2020
wjh15101051
ღゝ◡╹)ノ♡