[福建师大附中OJ 1264]烽火台

来源:互联网 发布:淘宝延迟收货在哪里 编辑:程序博客网 时间:2024/04/24 06:55

题目描述

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

输入

输入的第一行有两个整数,分别为n和m。第二行有n个整数,分别表示每个烽火台发出信息的代价。

输出

输出仅有一行,为所求的最小代价。

样例输入

5 31 2 5 6 2

样例输出

4

提示

0<=n<=500000

0<=m<=n

数据保证运算在longint范围内

题解:
填坑中….
动态规划。
f[i]表示为[1,i]的区间中,最后取的烽火台是第i个的最小花费。
f[0]=0
f[i]=min(f[i],f[j])+a[i]
(j[max(0,im),i))
然后显然答案是min(f[i])
(i[nm+1,n])
然后因为n很大,转移过程又只需要找区间最小值就行,那么只需要一个线段树维护一下就OK了

#include<iostream>#include<cstdlib>#include<algorithm>#include<cstring>#include<cstdio>#include<cmath>#define LiangJiaJun main#define INF 1999122700using namespace std;int n,m,a[500004];int tr[2000004],up=1;int query(int l,int r){    int ans=INF;    for(l=l+up-1,r=r+up+1;r-l>1;r>>=1,l>>=1){        if(~l&1)ans=min(ans,tr[l+1]);        if(r&1)ans=min(ans,tr[r-1]);    }    return ans;}void modify(int x,int pos){     pos += up;     tr[pos]=x;     pos>>=1;     while(pos){         tr[pos]=min(tr[pos<<1],tr[pos<<1|1]);         pos>>=1;     }     return ;}int LiangJiaJun (){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)scanf("%d",&a[i]);    while(up<n+2)up<<=1;    for(int i=1+up;i<=n+up;i++)tr[i]=INF;    for(int i=up;i>=1;i--)tr[i]=min(tr[i<<1],tr[i<<1|1]);    modify(0,1);    for(int i=1+1;i<=n+1;i++){        int lp=query(max(0+1,i-m),i-1)+a[i];        modify(lp,i);    }    printf("%d\n",query(n-m+1+1,n+1));    return 0;}
原创粉丝点击