【SSL】烽火传递

烽火传递


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。

题目分析

由题可列出方程: F [ i ] = m i n ( F [ j ] ) + a [ i ] ( i − m < j < i ) F[i]=min(F[j])+a[i](i−m<j<i) F[i]=min(F[j])+a[i](im<j<i)
方程中的 m i n min min部分我们要用单调队列来实现

代码

#include<iostream>
#include<deque>
#include<cstdio>
#include<algorithm>
#include<iomanip>
using namespace std;
long long n,m,a[100005],f[100005],x,big=2147483647;
deque<int> b;
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
     cin>>a[i];
    for(int i=1;i<=n;i++)
    {
    	while(b.size()!=0&&f[b.back()]>=f[i-1]) b.pop_back();//保持单调
    	b.push_back(i-1);//从队尾入队
    	while(b.size()!=0&&b.front()<i-m) b.pop_front();
    	f[i]=f[b.front()]+a[i];
    	if(i>=n-m+1) big=min(big,f[i]);//方程
	}
	cout<<big;
	return 0;
}


谢谢阅读,如有疑惑可在评论区留言

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值