poj 3368 Frequent values 线段树

来源:互联网 发布:php网页视频直播源码 编辑:程序博客网 时间:2024/05/29 07:15

题目大意

给一个长度为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.

1 0
原创粉丝点击