tyvj p1313(烽火传递)(80=>100分)

假如不看数据的话,是一道很简单的动态规划的题目。

很容易想到方程: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.                        
posted @ 2012-12-01 21:38  改名字干什么  阅读(154)  评论(0编辑  收藏  举报