【DP】最大子序列的和 (sequence)

最大子序列的和 (sequence)

     输入一个长度为n的整数序列(A1,A2,……,An),从中找出一段长度不超
过m 的连续的子序列,使得这个序列的和最大。
例如:序列  1,-3,5, 1,-2,3
当M=2 或3 时,S=5+1=6,当M=4 时,S=5+1-2+3=7
输入文件:(input.txt)
     第一行为两个数n 和m ,第二行为不超过integer 的n 个整数,两个数之
间用一个空格隔开。
输出文件: (output.txt)
     最大的子序列和。
样例输入:
6 3
1 -3 5 1 -2 3
样例输出:
6
数据范围:

 50%的数据N,M<=1000
 100%的数据N,M<=20000

====================================

===========================

朴素n^2,由于数据较若可以全过

-------------------------------------------

var  {50分算法}
  n,m:longint;
  a:array[1..20000]of longint;
  sum:array[0..20000]of longint;
procedure init;
begin
  assign(input,'sequence.in');
  assign(output,'sequence.out');
  reset(input); rewrite(output);
end;

procedure terminate;
begin
  close(input); close(output);
  halt;
end;

function max(a,b:longint):longint;
begin
  if a>b then exit(a);
  exit(b);
end;

procedure main;
var
  i,j:longint;
  ans:longint;
begin
  readln(n,m);
  sum[0]:=0;
  for i:=1 to n do
    begin
      read(a[i]);
      sum[i]:=sum[i-1]+a[i];
    end;
  ans:=-maxlongint;
  for i:=1 to n do
    for j:=i-1 downto max(0,i-m) do
    begin
      if sum[i]-sum[j]>ans then ans:=sum[i]-sum[j];
    end;
  writeln(ans);
end;

begin
  init;
  main;
  terminate;
end.

---------------------------------------------------------------

单调队列优化。

期望得分100分

----------------------------------------

var
  n,m:longint;
  a:array[0..200000]of longint;
  q:array[0..200000]of longint;
  sum:array[0..200000]of longint;
  
procedure init;
begin
  assign(input,'sequence.in');
  assign(output,'sequence.out');
  reset(input); rewrite(output);
end;

procedure terminate;
begin
  close(input); close(output);
  halt;
end;

function max(a,b:longint):longint;
begin
  if a>b then exit(a);
  exit(b);
end;

procedure main;
var
  i,j:longint;
  ans:longint;
  l,r:longint;
begin
  readln(n,m);
  sum[0]:=0;
  for i:=1 to n do
    begin
      read(a[i]);
      sum[i]:=sum[i-1]+a[i];
    end;
  l:=0; r:=0;
  fillchar(q,sizeof(q),0);
  ans:=-maxlongint;
  for i:=1 to n do
    begin
      while (l<=r)and(i-q[l]>m) do inc(l);             {维护区间的长度<=m}
      while (l<=r)and(sum[q[r]]>=sum[i]) do dec(r);    {从队尾开始剔除不可能点}
      inc(r);
      q[r]:=i;
      if l=r then {队列中只有一个元素的情况特殊考虑}
        begin
          if sum[i]-sum[i-1]>ans then ans:=sum[i]-sum[i-1];
        end
        else
         if sum[i]-sum[q[l]]>ans then ans:=sum[i]-sum[q[l]];
    end;
  writeln(ans);
end;

begin
  init;
  main;
  terminate;
end.             



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值