poj 3368 (线段树pascal)

来源:互联网 发布:恒韵琴行 淘宝 编辑:程序博客网 时间:2024/05/21 08:43

Description

You are given a sequence of n integers a1 ,a2 , ... , an in non-decreasing order. In addition to that, you aregiven several queries consisting of indices i and j (1 ≤ i≤ j ≤ n). For each query, determine the most frequent value among the integers ai ,... , aj.

Input

The input consists of several test cases.Each test case starts with a line containing two integers n and q (1≤ n, q ≤ 100000). The next line containsn integers a1 , ... , an (-100000≤ ai ≤ 100000, for each i ∈ {1, ..., n}) separated by spaces. You can assume that for each i∈ {1, ...,n-1}: ai≤ ai+1. The following q lines contain one query each,consisting of two integers i and j (1 ≤ i ≤ j ≤ n), whichindicate the boundary indices for the 
query.

The last test case is followed by a linecontaining a single 0.

Output

For each query, print one line with oneinteger: The number of occurrences of the most frequent value within the givenrange.

Sample Input

10 3

-1 -1 1 1 1 1 3 10 10 10

2 3

1 10

5 10

0

Sample Output

1

4

3

题目大意:

给一个长度为n的不降序列a1,a2,a3,…,an,有q个询问,每个询问为:i  j,询问在子序列ai…aj中出现最多的元素。注意有多组数据,以0结束。

数据范围:1 <=n, q <= 100000

 

分析:

 我们先开一棵线段树,用l,r来记录该区间的最左数,最右数,x,y,ans来表示最左的数出现的次数,最右数出现的次数,区间中间(处左右两边)出现最多的次数。

Father:L=lchild.L  R=rchild.R

If左儿子的数都相同而且左儿子的数等于右儿子的左边

Then Father.x=Lchild.x+Rchild.x else Father.x=Lchild.x

Father.y 同理。

Father.Ans有两种可能,一是如果左儿子的右边和右儿子的左边相同,加上两边一起判断即可。

father.ans=max(lchild.ans,rchild.ans,lchild.y+rchild.x);

如果左儿子的右边和右儿子的左边不相同,那么就多了两个区间加上两边一起判断即可。

father.ans=max(lchild.ans,rchild.ans,lchild.y,rchild,y);

然后查找也同理,不过最后的t[root].ans不是最大的值,因为最大值不一定在中间,也有可能在两边。

Ans=max(root.ans,root.x,root.y);

标程:

type

  arr=record

    l,r:longint;

   fl,fr,fmax:longint;

  end;

var

 tree:array [0..300001] of arr;

  a:array[0..100001] of longint;

  n,m:longint;

function min(o,p:longint):longint;

begin

  ifo<p then exit(o);

  exit(p);

end;

 

procedure ins(p,b,e:longint);

var

  m:longint;

begin

 tree[p].l:=b; tree[p].r:=e;

  if (b=e)then

    begin

     tree[p].fl:=1;

     tree[p].fr:=1;

     tree[p].fmax:=1;

     exit;

    end;

  m:=(b+e)shr 1;

  ins(p*2,b,m);

  ins(p*2+1,m+1,e);

 tree[p].fl:=tree[p*2].fl;

 tree[p].fr:=tree[p*2+1].fr;

  ifa[tree[p*2].r]=a[tree[p*2+1].l] then

    begin

     tree[p].fmax:=tree[p*2].fr+tree[p*2+1].fl;

     if a[tree[p].r]=a[tree[p*2+1].l] then

       tree[p].fr:=tree[p].fmax;

     if a[tree[p].l]=a[tree[p*2].r] then

        tree[p].fl:=tree[p].fmax;

    endelse tree[p].fmax:=1;

  iftree[p*2].fmax>tree[p].fmax then

   tree[p].fmax:=tree[p*2].fmax;

  iftree[p*2+1].fmax>tree[p].fmax then

   tree[p].fmax:=tree[p*2+1].fmax;

end;

 

function count(p,b,e:longint):longint;

var

 max1,max2:longint;

begin

  withtree[p] do

    begin

     if (b<=l) and (e>=r) then exit(fmax);

     if e<=tree[p*2].r then

       exit(count(p*2,b,e));

     if b>=tree[p*2+1].l then

       exit(count(p*2+1,b,e));

     count:=1;

     if a[tree[p*2].r]=a[tree[p*2+1].l] then

       count:=min(tree[p*2].r-b+1,tree[p*2].fr)+min(e-tree[p*2+1].l+1,tree[p*2+1].fl);

     max1:=count(p*2,b,tree[p*2].r);

     max2:=count(p*2+1,tree[p*2+1].l,e);

     if max1>count then count:=max1;

     if max2>count then count:=max2;

    end;

end;

 

procedure main;

var

  i,x,y:longint;

begin

  while1=1 do

    begin

     read(n);

     if n=0 then exit;

     readln(m);

     for i:=1 to n do

        read(a[i]);

     ins(1,1,n);

     for i:=1 to m do

       begin

         readln(x,y);

         writeln(count(1,x,y));

       end;

    end;

end;

 

begin

 main;

end.

 

0 0
原创粉丝点击