题目大意
给一个长度为n的不降序列a1,a2,a3,…,an,有q个询问,每个询问为:i j
询问在子序列ai…aj中出现最多的元素。
数据范围:1 <= n, q <= 100000
分析
注意到题目描述中的“不降序列”,让我们联想到可以使用线段树这一数据结构。
对于线段树的每一个节点:
记录left[k]表示当前区间最左边连续的元素有多少个
记录right[k]表示当前区间最右边连续的元素有多少个
记录max[k]表示当前区间中出现最多的元素有多少(当然它们是连续的)
当然,还要储存这些区间是什么数。
对于每一次询问,则可用类似方法,得到区间[i,j]中最左边连续元素的个数,最右边连续元素的个数,以及最多的连续元素的个数。
自己见代码
代码
type
pnode=^tnode;
tnode=record
lc,rc:pnode;
a,b,c:longint;
m1,m2,m3:longint;
end;
type
arr=record
a,b,c:longint;
m1,m2,m3:longint;
end;
var
t:pnode;
i,j,k:longint;
x,y:longint;
n,m:longint;
ans:arr;
f:array[0..100002] of longint;
procedure neww(var t:pnode);
begin
if t=nil then
begin
new(t);
t^.c:=0;
t^.lc:=nil;
t^.rc:=nil;
end;
end;
function max(x,y:longint):longint;
begin
if x>y then exit(x)
else exit(y);
end;
procedure insert(var t:pnode; l,r:longint);
var
i,j,k:longint;
mid:longint;
begin
with t^ do
begin
{if c=0 then
begin }
mid:=(l+r) div 2;
if l=r
then
begin
a:=1; b:=1; c:=1;
m1:=f[l]; m2:=f[l]; m3:=f[l];
exit;
end;
neww(lc);
neww(rc);
insert(lc,l,mid);
insert(rc,mid+1,r);
c:=max(lc^.c,rc^.c);
if c=lc^.c then m3:=lc^.m3
else m3:=rc^.m3;
if lc^.m2=rc^.m1
then
begin
c:=max(c,lc^.b+rc^.a);
m3:=lc^.m2;
end;
a:=lc^.a;
m1:=lc^.m1;
if lc^.m1=rc^.m1
then a:=a+rc^.a;
b:=rc^.b;
m2:=rc^.m2;
if lc^.m2=rc^.m2
then b:=b+lc^.b;
end;
{end;}
end;
function find(t:pnode;l,r,x,y:longint):arr;
var
mid:longint;
l1,r1:arr;
begin
if t=nil then exit;
with t^ do
begin
mid:=(l+r) div 2;
if (l=x) and (r=y)
then
begin
find.a:=a; find.b:=b; find.c:=c;
find.m1:=m1; find.m2:=m2; find.m3:=m3;
exit;
end;
if (l<=x) and (mid>=y)
then
begin
find:=find(lc,l,mid,x,y);
exit;
end;
if (mid<x) and (r>=y)
then
begin
find:=find(rc,mid+1,r,x,y);
exit;
end;
l1:=find(lc,l,mid,x,mid);
r1:=find(rc,mid+1,r,mid+1,y);
with find do begin
c:=max(l1.c,r1.c);
if c=l1.c then m3:=l1.m3
else m3:=r1.m3;
if l1.m2=r1.m1
then
begin
c:=max(c,l1.b+r1.a);
m3:=l1.m2;
end;
a:=l1.a;
m1:=l1.m1;
if l1.m1=r1.m1
then a:=a+r1.a;
b:=r1.b;
m2:=r1.m2;
if l1.m2=r1.m2
then b:=b+l1.b;
end;
end;
end;
begin
while true do
begin
read(m);
if m=0 then break;
fillchar(f,sizeof(f),0);
dispose(t);
readln(n);
for i:=1 to m do
read(f[i]);
readln;
fillchar(t,sizeof(t),0);
neww(t);
insert(t,1,m);
for i:=1 to n do
begin
readln(x,y);
ans:=find(t,1,m,x,y);
writeln(ans.c);
end;
end;
end.