RMQ——忠诚题解

题目:忠诚

描述:

【题目描述】

老管家是一个聪明能干的人。他为财主工作了整整10年,财主为了让自已账目更加清楚。要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满 意。但是由于一些人的挑拨,财主还是对管家产生了怀疑。于是他决定用一种特别的方法来判断管家的忠诚,他把每次的账目按1,2,3…编号,然后不定时的问 管家问题,问题是这样的:在a到b号账中最少的一笔是多少?为了让管家没时间作假他总是一次问多个问题。

【输入格式】


输入中第一行有两个数m,n表示有m(m<=100000)笔账,n表示有n个问题,n<=100000。

第二行为m个数,分别是账目的钱数

后面n行分别是n个问题,每行有2个数字说明开始结束的账目编号


【输出格式】

输出文件中为每个问题的答案。具体查看样例。

【样例输入】


10 3

1 2 3 4 5 6 7 8 9 10

2 7

3 9

1 10


【样例输出】

2 3 1

【来源】

hzoi 2014 寒川

该题较水,不用想,果的RMQ算法,直接敲代码就行了,但是这个求的是最小值,所以再多加了一步数组初始化的处理。但是因为写的时候手残少打了一个零,所以后两个点W了(居然不是E……对COGS的评测机无语了)。最后反复交了几次,终于A掉了。

AC代码:

{

program zht;
var
i,j,n,m:longint;
x,l,r:longint;
a:array[0..100000] of int64;
f:array[0..100000,0..20] of int64;

function min(a,b:int64):int64;
begin
if a<b then min:=a else min:=b;
end;

begin
assign(input,'faithful.in');
assign(output,'faithful.out');
reset(input);
rewrite(output);

readln(n,m);


fillchar(f,sizeof(f),$7f);

for i:=1 to n do
begin
read(a[i]);
f[i,0]:=a[i];
end;


for j:=1 to trunc(ln(n)/ln(2)) do
 for i:=1 to n+1-(1 shl j) do
  f[i,j]:=min(f[i,j-1],f[i+1 shl (j-1),j-1]);

for i:=1 to m do
 begin
 readln(l,r);
 x:=trunc(ln(r-l+1)/ln(2));
 write(min(f[l,x],f[r+1-(1 shl x),x]),' ');
 end;

close(input);
close(output);
end.
}
<Marvolo原创,严禁转载>
原文地址:https://www.cnblogs.com/zhtjtcz/p/4992829.html