题目大意:
一个数列,取出一些数使得它们的总和最大且没有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 }