普通sequence

题目

首先是一个数据范围为2000的,这个可以用平方算法做。

要使它成为一个非降序列的合并次数最小,我们可以贪心地想到要使合并后的值尽量小,不然就会导致后面需要的合并次数增多。

我们用c[i]记录前缀和,f[i]表示以i结尾的这一段序列的最后一个元素的值,g[i]表示到i为止的合并次数,那么就可以得到一个转移方程。

f[i]=c[i]-c[j](f[j]<=c[i]-c[j])

g[i]=g[j]+i-j-1;

因为c[i]-c[j]在downto的过程中是单调递增的,所以只要找到一个可以转移的就可以break了。

View Code
program Neayo;
const
        inf='sequence.in';
        ouf='sequence.out';
var
        i,j,k,m,n,ans:longint;
        g,f,c:array[0..1502]of longint;
procedure init;
var x:longint;
begin
     assign(input,inf);assign(output,ouf);
     reset(input);rewrite(output);
     readln(n);
     for i:=1 to n do
     begin
          read(x);
          c[i]:=c[i-1]+x;
     end;
     close(input);
end;
procedure go;
begin
     fillchar(f,sizeof(f),127);
     f[0]:=0;g[0]:=0;
     for i:=1 to n do
      for j:=i-1 downto 0 do
      if c[i]-c[j]>=f[j] then
      begin
           f[i]:=c[i]-c[j];
           g[i]:=g[j]+i-j-1;
           break;
      end;
    writeln(g[i]);
end;
begin
     init;
     go;
     close(output);
end.

到了1000000的数据范围,平方算法是绝对不可行的了。

但是转移方程还是正确的,由于它的单调性,于是我们加入单调队列将决策过程优化成O(nlogn)。

View Code
 1 const
 2         inf='ccl.in';
 3         ouf='ccl.out';
 4 var
 5         i,j,k,n:longint;
 6         ans:longint;
 7         c:array[0..1000001]of int64;
 8         g,f,q:array[0..1000001]of int64;
 9 procedure init;
10 begin
11      assign(input,inf);assign(output,ouf);
12      reset(input);rewrite(output);
13      readln(n);
14      for i:=1 to n do
15      begin
16           read(c[i]);
17           c[i]:=c[i-1]+c[i];
18      end;
19      close(input);
20 end;
21 procedure go;
22 var l,r:longint;
23 begin
24      fillchar(f,sizeof(f),127);
25      l:=1;r:=1;f[0]:=0;q[1]:=0;
26      for i:=1 to n do
27      begin
28           while (l<r)and(c[i]>=f[q[l+1]])do inc(l);
29           f[i]:=c[i]-c[q[l]]+c[i];
30           g[i]:=g[q[l]]+i-q[l]-1;
31           while (r>l)and(f[i]<=f[q[r]])do dec(r);
32           inc(r);
33           q[r]:=i;
34      end;
35      writeln(g[n]);
36 end;
37 begin
38      init;
39      go;
40      close(output);
41 end.

转载于:https://www.cnblogs.com/neayo/archive/2012/11/06/2757179.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值