[JSOI]选数

背景 Background
JSOI2012春季函授A层次第一讲
描述 Description
 大J和小L经常在一起讨论一些有趣的问题,今天他们准备了n张纸条,每张纸条上写一个整数,然后将纸条排成一列。要求从中取连续的若干张,但张数不能太多也不能太少,小L决定张数的范围,看谁取到的纸条上的数的和最小。你有好方法吗?
输入格式 Input Format
 输入文件一共3行,第一行为一个整数(N≤32767),表示纸条张数,第二行为两个整数L,U(L≤U≤N),表示所取纸条张数的范围,第三行为n个整数,分别表示纸条上所写的数。
输出格式 Output Format
一个正整数,满足条件的最小值。
样例输入 Sample Input
10
2 8
1 32 -432 -2 43 -65 -543 -23 34 654

样例输出 Sample Output
-1022
-------------------------------------------------------------------------------------------------------------------
网上看到的题,试着写了写,挺有趣的~
思路一(AC):
附源代码:

program Rmq;

const
     maxn=32768;
var
   sum:array[0..maxn] of longint;
   f:array[0..maxn,0..15] of longint;
   L,U,N:longint;
function log2(x:longint):longint;
begin
     log2:=0;
     while x>1 do begin
           x:=x shr 1;
           inc(log2);
     end;
end;
function max(a,b:longint):longint;
begin
     if a>b then exit(a) else exit(b);
end;
procedure init;
var
   i,j,k,len:longint;
begin
     readln(N);
     readln(L,U);
     sum[0]:=0;
     f[0,0]:=0;
     for i:=1 to N do begin
         read(sum[i]);
         inc(sum[i],sum[i-1]);
         f[i,0]:=sum[i];
     end;
     {RMQ-Init}
     len:=1;
     for j:=1 to log2(N) do begin
         for i:=0 to N do begin
             k:=i+len;
             if k<=N then
                f[i,j]:=max(f[i,j-1],f[k,j-1])
             else f[i,j]:=f[i-1,j];
         end;
         len:=len shl 1;
     end;
end;
function rmq(l,r:longint):longint;
var
   p:longint;
begin
     p:=log2(r-l+1);
     if f[l,p]>f[r-(1 shl p)+1,p] then
        exit(f[l,p])
     else exit(f[r-(1 shl p)+1,p]);
end;
procedure main;
var
   ans,i,temp:longint;
begin
     init;
     ans:=maxlongint;
     for i:=L to N do begin
         temp:=sum[i]-rmq(max(0,i-U),i-L);
         if temp<ans then ans:=temp;
     end;
     write(ans);
end;
procedure debug;
var
   i,j:longint;
begin
     for i:=0 to N do writeln('Sum[',i,']:=',sum[i]);
     for i:=0 to N do
         for j:=0 to log2(N) do
             writeln('F[',i,',',j,']:=',f[i,j]);
end;
begin
     assign(input,'Rmq.in');
     assign(output,'Rmq.out');
     reset(input);
     rewrite(output);
     main;
     debug;
     close(input);
     close(output);
end.
思路 二(待测试):

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值