题目描述
在一年前赢得了小镇的最佳草坪比赛后,Farm John变得很懒,再也没有修剪过草坪。现在,新一轮的最佳草坪比赛又开始了,Farm John希望能够再次夺冠。
然而,Farm John的草坪非常脏乱,因此,Farm John只能够让他的奶牛来完成这项工作。Farm John有N(1 <= N <= 100,000)只排成一排的奶牛,编号为1...N。每只奶牛的效率是不同的,奶牛i的效率为E_i(0 <= E_i <= 1,000,000,000)。
靠近的奶牛们很熟悉,因此,如果Farm John安排超过K只连续的奶牛,那么,这些奶牛就会罢工去开派对:)。因此,现在Farm John需要你的帮助,计算FJ可以得到的最大效率,并且该方案中没有连续的超过K只奶牛。
输入格式
第一行:空格隔开的两个整数 N 和 K
第二到 N+1 行:第 i+1 行有一个整数 E_i
输出格式
第一行:一个值,表示 Farm John 可以得到的最大的效率值。
输入输出样例
输入 #1
5 2 1 2 3 4 5
输出 #1
12
分析
(1) 记得开long long
(2) 左闭右开的对列访问队尾要用 r - 1
(3)将方程变形使其可以用单调队列优化
(4)当状态不对,空间大了的话,可以尝试将状态下放到每一个元素上
(5)注意初始状态,初始化,边界条件。比如开始时还没到k时,可以在队列中插入一个0。以免将第一个漏掉(因为转移是用的dp[q[l]][0])其中无法包含第一个
代码
/*************************** User:Mandy.H.Y Language:c++ Problem:luogu2627 Algorithm: Date:2019.8.30 ***************************/ #include<bits/stdc++.h> #define Max(x,y) ((x) > (y) ? (x) : (y)) #define Min(x,y) ((x) < (y) ? (x) : (y)) using namespace std; const int maxn = 1e5 + 5; int n,k,l,r; long long dp[maxn][3]; long long sum[maxn],q[maxn]; //dp[第i只牛][是否包含自身] template<class T>inline void read(T &x){ x = 0;bool flag = 0;char ch = getchar(); while( ! isdigit(ch)) flag |= ch == '-',ch = getchar(); while(isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48),ch = getchar(); if(flag) x = -x; } template<class T>void putch(const T x){ if(x > 9) putch(x / 10); putchar(x % 10 | 48); } template<class T>void put(const T x){ if(x < 0) putchar('-'),putch(-x); else putch(x); } void file(){ freopen("testdata.in","r",stdin); // freopen("2627.out","w",stdout); } void readdata(){ read(n);read(k); for(int i = 1;i <= n; ++ i){ read(sum[i]); sum[i] += sum[i-1]; } } void work(){ q[r++] = 0;//主要是为了前几个还没到k的考虑 //因为 dp[q[l]][0] - sum[q[l]]可能小于0 , //所以前面可能出现连加,加上0以免将前几个漏了 //因为 dp[q[l]][0]不包括自身 for(int i = 1;i <= n; ++ i){ while(l < r && q[l] < i-k) l++; dp[i][0] = Max(dp[i-1][0],dp[i-1][1]); if(l < r) dp[i][1] = dp[q[l]][0] - sum[q[l]] + sum[i]; else dp[i][1] = sum[i] - sum[i-1]; while(l < r && dp[q[r-1]][0] - sum[q[r-1]] <= dp[i][0] - sum[i]) r--; //注意是r - 1; q[r++] = (long long)i; } put(Max(dp[n][0],dp[n][1])); } int main(){ // file(); readdata(); work(); return 0; }