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.
原文地址:https://www.cnblogs.com/yinwuxiao/p/8013057.html