luogu 2627 修建草坪

题目大意:

一个数列,取出一些数使得它们的总和最大且没有k个连续

思路:

首先我们可以找到一个nk的dp

dp方程:dp[i]=dp[i-1]+sum[i]-sum[j] (sum[j]尽量小)

然后我们可以使用单调队列(单减)优化掉k即简化掉求最小值的一步

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<queue>
 8 #include<vector>
 9 #include<set>
10 #include<stack>
11 #define inf 2147483611
12 #define ll long long
13 #define MAXN 100100
14 using namespace std;
15 inline int read()
16 {
17     int x=0,f=1;
18     char ch=getchar();
19     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
20     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
21     return x*f;
22 }
23 int n,a[MAXN],k;
24 ll dp[MAXN],s,ans;
25 struct data
26 {
27     ll val,pos;
28 }q[MAXN];
29 int main()
30 {
31     n=read(),k=read();
32     int head=0,tail=1;
33     for(int i=1;i<=n;i++)
34     {
35         a[i]=read();s+=a[i];
36         ll tmp=dp[i-1]-s;
37         while(head<=tail&&q[tail].val<tmp) tail--;
38         q[++tail]=(data) {tmp,i};
39         while(head<=tail&&q[head].pos<i-k) head++;
40         dp[i]=q[head].val+s;
41     }
42     printf("%lld",dp[n]);
43 }
View Code
原文地址:https://www.cnblogs.com/yyc-jack-0920/p/7686860.html