烽火台又称烽燧,是重要的防御设施,一般建在险要处或交通
要道上。一旦有敌情发生,白天燃烧柴草,通过浓烟表达信息: 夜晚燃烧干柴,以火光传递军情。在某两座城市之间有n个烽火台 ,每个烽火台发出信号都有一定的代价。为了使情报准确的传递 ,在m个烽火台中至少要有一个发出信号。现输入n、m和每个烽火 台发出的信号的代价,请计算总共最少需要话费多少代价,才能 使敌军来袭之时,情报能在这两座城市之间准确的传递!!!输入格式 InputFormat
第一行有两个数n,m分别表示n个烽火台,在m个烽火台中至少要有 一个发出信号。第二行为n个数,表示每一个烽火台的代价。输出格式 OutputFormat
一个数,即最小代价。样例输入 SampleInput
5 31 2 5 6 2样例输出 SampleOutput
4数据范围和注释 Hint
1<=n,m<=1,000,000时间限制 TimeLimitation
各个测试点1s解题报告
搜到的单调队列方法的题解只有代码……于是把代码扒下来看了n遍终于搞懂了。单调队列优化dp,记f[i]为第i位必选时所能达到的最小代价,所以可以写出方程 f[i]=min(f[j])+a[i],j=i-m..i-1 。单调队列维护f的值,以保证每次取min(f[j])为O(1)的复杂度。目标状态为 f[n-m+1]..f[m] 中的最小值。代码
View Code
1 var 2 a,q,f:array[1..1000001]of longint; 3 m,n,i,h,t,ans:longint; 4 begin 5 read(m,n); 6 for i:=1 to n do read(a[i]); 7 t:=0; 8 h:=1; 9 ans:=1000000001;10 for i:=1 to n do begin11 while ((i-m)>q[h])and(h<=t) do inc(h);12 while (f[i-1]=h) do dec13 14 (t);15 inc(t);16 q[t]:=i-1;17 f[i]:=a[i]+f[q[h]];18 end;19 for i:=n-m+1 to n do if ans>f[i] then ans:=f[i];20 writeln(ans);21 end.