uva-11235
题意:
给出一个非降序排列的数组,对于一系列询问(i,j),输出ai——aj中出现次数最多的值出现的次数。
题解:
首先注意到序列是非降序的
所以连续的数字一定是连在一起的
所以对于查找一段区间,我们可以考虑预处理
首先进行游程编码
例如-1,1,1,2,2,2,4可写成(-1,1),(1,2),(2,3),(4,1)
之后利用rmq进行区间最大值维护
对于每一次查询,应查询起点所在的后一个区间-----终点所在的前一个区间
再考虑两边多出来的部分
另外处理时有一些细节需要注意
*以下程序的二分查找完全可以用预处理替代
代码:
uses math;
var
i,j,o,start,maxn,n,m,y,x,c,d,ll,tmp:longint;
a,v,h,t:array[0..100000]of longint;
bz:array[1..100000,0..20]of longint;
function find(x:longint):longint;
var hh,t,mid:longint;
begin
hh:=0; t:=ll;
while hh<t do
begin
mid:=(hh+t) div 2+1;
if h[mid]<x then hh:=mid else t:=mid-1;
end;
exit(hh);
end;
function find2(x:longint):longint;
var hh,t,mid:longint;
begin
hh:=0; t:=ll;
while hh<t do
begin
mid:=(hh+t) div 2+1;
if h[mid]<=x then hh:=mid else t:=mid-1;
end;
exit(hh);
end;
begin
readln(n,m);
while n<>0 do
begin
for i:=1 to n do read(a[i]);
start:=1; ll:=0;
for i:=1 to n do
if (i<>1) and (a[i]<>a[i-1]) then
begin
inc(ll); h[ll]:=start; t[ll]:=i-1;
start:=i; bz[ll,0]:=(t[ll]-h[ll]+1);
end;
inc(ll); h[ll]:=start; t[ll]:=n; bz[ll,0]:=(t[ll]-h[ll]+1);
for j:=1 to 20 do
for i:=1 to ll do
if i+(1<<j)-1<=ll then
bz[i,j]:=max(bz[i,j-1],bz[i+(1<<(j-1)),j-1]);
for i:=1 to m do
begin
read(c,d);
x:=find(c)+1; y:=find2(d)-1; maxn:=1;
if x<=y then
begin
o:=trunc(ln(y-x+1)/ln(2));
maxn:=max(bz[x,o],bz[y-(1<<o)+1,o]);
end;
maxn:=max(maxn,h[x]-c);
maxn:=max(maxn,d-t[y]);
maxn:=min(maxn,d-c+1);
writeln(maxn);
end;
readln(n,m);
end;
end.