台州 OJ 3847 Mowing the Lawn 线性DP 单调队列
描述
After winning the annual town competition for best lawn a year ago, Farmer John has grown lazy; he has not mowed the lawn since then and thus his lawn has become unruly. However, the competition is once again coming soon, and FJ would like to get his lawn into tiptop shape so that he can claim the title.
Unfortunately, FJ has realized that his lawn is so unkempt that he will need to get some of his N (1 <= N <= 100,000) cows, who are lined up in a row and conveniently numbered 1..N, to help him. Some cows are more efficient than others at mowing the lawn; cow i has efficiency E_i (0 <= E_i <= 1,000,000,000).
FJ has noticed that cows near each other in line often know each other well; he has also discovered that if he chooses more than K (1 <= K <= N) consecutive (adjacent) cows to help him, they will ignore the lawn and start a party instead. Thus, FJ needs you to
assist him: determine the largest total cow efficiency FJ can obtain without choosing more than K consecutive cows.
输入
* Line 1: Two space-separated integers: N and K
* Lines 2..N+1: Line i+1 contains the single integer: E_i
输出
* Line 1: A single integer that is the best total efficiency FJ can obtain.
#include <iostream> #include <cstring> #define LL __int64 using namespace std; const int MAX = 100005; LL dp[MAX]; //不放 i 时,前 i 个数字组成的序列,去掉的数字的最小和 LL que[MAX]; //单调队列 int pos[MAX]; //队列中元素对应的下标 int front, rear; int n, m; int main(){ // freopen("input.txt", "r", stdin); // freopen("output.txt", "w", stdout); scanf("%d%d", &n, &m); LL num; LL sum = 0; LL ans; memset(dp, 0x3f, sizeof(dp)); dp[0] = 0; //去掉第一个 front = 0; rear = 1; //初始化单调队列 que[rear] = 0; pos[rear] = 0; for(int i=1; i<=n; i++){ if(rear != front && pos[front+1] < i-m-1){ //如果前面的数字过期了 front++; } scanf("%I64d", &num); sum += num; //计算 dp[i] dp[i] = que[front+1] + num; //将 dp[i] 放入队列 while(rear != front && que[rear] > dp[i]){ rear--; } que[++rear] = dp[i]; pos[rear] = i; if(i == n-m){ ans = dp[i]; } if(i >= n-m){ ans = min(ans, dp[i]); } } //最后 m+1 个数字中,在哪个地方断开 printf("%I64d\n", sum-ans); return 0; }