SSL_2883 烽火传递

SSL_2883 烽火传递 【单调性】

Description

烽火台又称烽燧,是重要的军事防御设施,一般建在险要或交通要道上。一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息;夜晚燃烧干柴,以火光传递军情,在某两座城市之间有n个烽火台,每个烽火台发出信号都有一定代价。为了使情报准确地传递,在连续 m 个烽火台中至少要有一个发出信号。请计算总共最少花费多少代价,才能使敌军来袭之时,情报能在这两座城市之间准确传递。

Input

第一行:两个整数 N,M。其中N表示烽火台的个数, M 表示在连续 m 个烽火台中至少要有一个发出信号。接下来 N 行,每行一个数 Wi,表示第i个烽火台发出信号所需代价。

Output

一行,表示答案。

Sample Input

5 3
1
2
5
6
2

Sample Output

4

Hint

对于50%的数据,M≤N≤1,000 。 对于100%的数据,M≤N≤100,000,Wi≤100。

这道题单纯用动归显然会超时,要用单调队列来优化。具体请看代码注释。

#include<iostream>
#include<cstdio>
#define maxx 200000
using namespace std;
int f[maxx],q[maxx],a[maxx],n,m,h,t;
int main(){
    
    
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
    
    
		scanf("%d",&a[i]);
	}
	for(int i=1;i<=n;i++){
    
    
		while(h<=t and f[i-1]<f[q[t]]) t--;	//当f[i-1]比队列尾部更优,就用f[i-1]替换掉队尾
		q[++t]=i-1;							//存储队列中元素的下标
		while(h<=t and q[h]<i-m) h++;		//如果队列元素离开维护范围,出队
		f[i]=f[q[h]]+a[i];					//状态转移
	}
	int ans=0x7fffffff;
	for(int i=n-m+1;i<=n;i++){
    
    				/*
		ans=min(ans,f[i]);					  在最后的m个元素中找到最小的
	}																	*/
	cout<<ans;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_54799322/article/details/114411363
今日推荐