bzoj1233

首先这道题有一个很重要的贪心就是

在保证所有干草堆都能参与搭建的前提下,我们尽量使最底层的宽度小,这样搭起来的的干草堆高度一定是最高的

当我们以第i个干草堆为一层,显然最优的情况是找到一个尽可能小的j (i<=j<=n)

使sum[j-1]-sum[i-1]>=h[j] (h[j]第j个干草堆为一层在满足上述条件下最小宽度)

显然朴素的遍历是O(n2),会超时;

如果对于j<k,对于后面的阶段i,如果h[j]-sum[j-1]<h[k]-sum[k-1] 那么j一定比k优

因为对于后面的阶段i,如果sum[k-1]-sum[i-1]>=h[k] 即h[k]-sum[k-1]<=-sum[i-1]

那么一定h[j]-sum[j-1]<=-sum[i-1]也成立,即j更小且满足条件,即j比k优

所以我们考虑用单调队列来维护这个性质

 1 var f,s,d,q:array[0..100010] of longint;
 2     n,i,x,h,t:longint;
 3 
 4 begin
 5   readln(n);
 6   for i:=1 to n do
 7   begin
 8     read(x);
 9     s[i]:=s[i-1]+x;
10   end;
11   q[1]:=n+1;
12   h:=1;
13   t:=1;
14   for i:=n downto 1 do
15   begin
16     while (h<t) and (s[q[h+1]-1]-s[i-1]>=d[q[h+1]]) do inc(h);
17     d[i]:=s[q[h]-1]-s[i-1];
18     f[i]:=f[q[h]]+1;
19     if i=1 then break;
20     while (h<t) and (d[i]-s[i-1]<d[q[t]]-s[q[t]-1]) do dec(t);
21     inc(t);
22     q[t]:=i;
23   end;
24   writeln(f[1]);
25 end.
View Code
原文地址:https://www.cnblogs.com/phile/p/4473155.html