poj 3368 Frequent values 线段树
题目大意
给一个长度为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.