题目链接:http://poj.org/problem?id=3368
RMQ,求的是在一个非降序列中任意区间[L,R]中同一个数出现最多的次数
在正常RMQ的基础上对于两端和中部分别特殊处理
贴代码
var n,Q:longint;
a,right,left:array[0..100005]of longint;
f:array[0..100005,0..20]of longint;
procedure init;
begin
assign(input,'Frequent.in');reset(input);
assign(output,'Frequent.out');rewrite(output);
end;
function max(x,y:longint):longint;
begin
if x>y then exit(x) else exit(y);
end;
function min(x,y:longint):longint;
begin
if x<y then exit(x) else exit(y);
end;
function work(i,j:longint):longint;
var k:longint;
begin
work:=max(min(j,right[i])-i+1,j-max(i,left[j])+1);
k:=(i+j)>>1;
work:=max(work,min(j,right[k])-max(i,left[k])+1);
end;
procedure main;
var i,j,L,R:longint;
begin
read(n);
while n<>0 do
begin
readln(Q);
for i:=1 to n do read(a[i]);
readln;
a[0]:=maxlongint;
a[n+1]:=maxlongint;
for i:=1 to n do
if a[i]=a[i-1] then left[i]:=left[i-1]
else left[i]:=i;
for i:=n downto 1 do
if a[i]=a[i+1] then right[i]:=right[i+1]
else right[i]:=i;
for i:=1 to n do f[i,0]:=1;
for j:=1 to trunc(ln(n)/ln(2)) do
for i:=1 to n-(1<<j)+1 do
f[i,j]:=max(max(f[i,j-1],f[i+1<<(j-1),j-1]),work(i,i+1<<j-1));
for i:=1 to Q do
begin
readln(L,R);
j:=trunc(ln(R-L+1)/ln(2));
writeln(max(max(f[L,j],f[R-(1<<j)+1,j]),work(L,R)));
end;
read(n);
end;
end;
procedure print;
begin
close(input);close(output);
end;
begin
// init;
main;
// print;
end.
【写的有漏洞的,欢迎路过大神吐槽】
2016/11/14 16:09:09
Ending.