台州 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.

题目的意思是给 n 个整数,从这 n 个整数中选出一些,并且连续部分的长度不能超过 k,求这些整数最大的和是多少。

转载一篇博客:http://blog.csdn.net/magical_qting/article/details/47205093   和这道题很相似

转换成上面链接里的那道题目,就是求,长度为 k+1 的连续部分中必有一个断点。

dp[i] 表示,第 i 个数字不选时,前 i-1 个数字中去掉的数字的和的最小值。

dp[i] = min(dp[x]) + num[i]  (i-k-1 <= x <= i-1)

求出去掉的数字的和的最小值后,用所有数字的和减去去掉的数字的和,就是答案了。

PS:台州的编译器有点不同,用 long long 貌似会出错,改成 64 位 int 就过了。

代码:

#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;
}

  

时间: 2024-11-07 19:42:16

台州 OJ 3847 Mowing the Lawn 线性DP 单调队列的相关文章

习题:烽火传递(DP+单调队列)

烽火传递[题目描述]烽火台又称烽燧,是重要的防御设施,一般建在险要处或交通要道上.一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息:夜晚燃烧干柴,以火光传递军情.在某两座城市之间有n个烽火台,每个烽火台发出信号都有一定的代价.为了使情报准确的传递,在m个烽火台中至少要有一个发出信号.现输入n.m和每个烽火台发出的信号的代价,请计算总共最少需要花费多少代价,才能使敌军来袭之时,情报能在这两座城市之间准确的传递!!![输入描述]第一行有两个数n,m(1<=n,m<=1000000)分别表示n个烽火台

poj3017 dp+单调队列

http://poj.org/problem?id=3017 Description Given an integer sequence { an } of length N, you are to cut the sequence into several parts every one of which is a consecutive subsequence of the original sequence. Every part must satisfy that the sum of

12170 - Easy Climb(DP+单调队列)

该题需要用数据结构来优化DP ,具体方法就是之前第八章讲的(用数据结构优化算法,紫书P241),使用一个数组和两个指针维护一个单调队列, 可以在O(n)的时间内求出滑动窗口中的最小值 . 有了这个优化我们就可以快速的求出dp[i-1][j](x-d<=j<=x+d)的最小值. 然而刘汝佳就是不这么做,他只用了一个指针,连维护优先队列的数组都没开,就"隐式的"求出了最小值 . 具体做法是: 1.先维护窗口左边界,别让指针k超出了窗口,如果x[k] < x[j] - d那

bzoj2500: 幸福的道路(树形dp+单调队列)

好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1]+dis[x][y] up:up[fa[x]]+dis[x][y] dfs1找向下,即向子节点的最长路 dfs2找向上的最长路 最后最长路f[i]=max(up[x],g[x][0]) 第二部分 找最长连续子序列,使得序列中abs(mx-mn)<=m 这次学习了用单调队列的做法 两个队列mx,mn

UESTC 594 我要长高 dp单调队列优化入门

//其实是个伪单调队列...渣渣刚入门 //戳这里:594 //dp[ i ][ j(现身高) ] = min(    dp[ i ][ k(现身高) ]  + fabs( j(现身高) - k(现身高) ) * C + ( j(现身高) - h[i](原身高) )  *( j(现身高) - h[i](原身高) )     ); 观察到可以单调队列优化,O(N * H * H)  —>  O(N * H) j >= k 时, dp[ i ][ j ] = min (    dp[ i ][ k

【烽火传递】dp + 单调队列优化

题目描述 烽火台又称烽燧,是重要的防御设施,一般建在险要处或交通要道上.一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息:夜晚燃烧干柴,以火光传递军情.在某两座城市之间有 n 个烽火台,每个烽火台发出信号都有一定的代价.为了使情报准确的传递,在 m 个烽火台中至少要有一个发出信号.现输入 n.m 和每个烽火台发出的信号的代价,请计算总共最少需要多少代价,才能使敌军来袭之时,情报能在这两座城市之间准确的传递! 输入格式 第一行有两个数 n,m 分别表示 n 个烽火台,在任意连续的 m 个烽火台中至少

BZOJ 2500 幸福的道路 树形DP+单调队列

题目大意:给定一棵树,令a[i]为从第i个节点出发的最长链,求a[i]中最长的区间,满足区间内最大值与最小值之差不超过m 读错题害死人,脑残害死人 求a[i]显然是树形DP 考虑从一个点出发的链可以从子节点走,也可以从父节点走 因此我们DP两次,第一次求出从子节点走的最长链,第二次求出从父节点走的最长链,两次取max就是答案 但是直接DP会有问题,因为从父节点走的最长链可能是从自己的子树出发的,这样就会走重 因此除记录从子节点出发的最长链外还要记录一个从另一个子节点出发的次长链,如果最长链长度相

UVaLive 3983 Robotruck (DP + 单调队列)

题意:有n个垃圾,第i个垃圾坐标为(xi,yi),重量为wi,有一个机器人,要按照编号从小到大的顺序剑气所有的垃圾兵扔进垃圾桶,垃圾桶在原点, 每次总重量不能超过C,两点间距离为曼哈顿距离,求出最短的距离和. 析:第一反应想到的状态是有个数和重量,一看,时间复杂度受不了,只能改.dp[i] 表示从原点出发倒掉前 i 个垃圾,并放到垃圾桶所要的最短距离. dp[i] = min{dp[j] + dist(j+1, i) + disttoorigin(i) + disttoorigin(j+1)}

复习【dp+单调队列】

处理10W数据:二分答案+单调队列+dp 这题可以用二维Dp和一维Dp来做,虽然两者时间复杂度都是O(N2),但二维的无法被优化,一维的可以用单调队列将时间效率缩为O(N).因此构造Dp时优先采用纬度小的方案. 单调队列的核心模板见代码. ps:在一部分单调队列的题目中,队列各项的数值会同时变化.此时应用变量Plus做维护 #include <iostream> using namespace std; struct qnode { long tim, x; }; const long N=1