假如不看数据的话,是一道很简单的动态规划的题目。
很容易想到方程:f[i]:=min(f[i],f[i-j]+s[i]);(1<=j<=m);这个是 O(mn)的算法
但是一看数据- - 一百万。
优化有两种方法,一种是用堆O(nlogn), 一种使用单调队列优化O(n)。
每次更新单调队列时,后面比当前状态f[i]大的全部踢走,然后把它加入队尾,同时把不能继续使用的值(序号小于当前序号减去m的值)踢走,保证了队列的单调递增性。
我们就有 f[i]:=s[i]+f[d[t]](t是队列的头指针,d储存队列的数组)。然后把f[i]加入到队列之中。
代码:
1 program p1313; 2 var 3 i,j,k,l,m,n,ans,t,w:longint; 4 f,s,d:array[0..1000000]of longint; 5 begin 6 assign(input,'p1313.in'); 7 assign(output,'haha.out'); 8 reset(input); 9 rewrite(output); 10 read(n,m); 11 for i:=1 to n do 12 read(s[i]); 13 for i:=1 to n do 14 f[i]:=s[i]; 15 w:=0; 16 for i:=1 to m do 17 begin 18 while(w>=0)and(f[d[w]]>f[i])do dec(w); 19 inc(w); 20 d[w]:=i; 21 end; 22 for i:=m+1 to n do 23 begin 24 while d[t]<i-m do inc(t); 25 f[i]:=f[i]+f[d[t]]; 26 while(w>=t)and(f[d[w]]>f[i])do dec(w); 27 inc(w); 28 d[w]:=i; 29 end; 30 ans:=maxlongint; 31 for i:=n-m+1 to n do 32 if ans>f[i] then ans:=f[i]; 33 write(ans); 34 close(input); 35 close(output); 36 end.