POJ3368(RMQ)

                                                     Frequent values

Description

You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In addition to that, you are given 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 contains n 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), which indicate the boundary indices for the 
query.

The last test case is followed by a line containing a single 0.(多组数据)

Output

For each query, print one line with one integer: The number of occurrences of the most frequent value within the given range.

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

解题思路:

可以求出相同数的的个数(可以离散),但是如果所求区间切断了连续区间怎么办,分成三段,左边一段,右边一段,中间的就可以用线段树(不用更新,RMQ要简单一点)或者RMQ算最大值。

具体代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #define N 100005
 5 using namespace std;
 6 int a[N],lo[N],pos[N];
 7 int n,m,x,y;
 8 struct ii
 9 {
10     int sta,end;
11     int num;
12 }aa[N];
13 int f[N][20];
14 int main()
15 {
16     freopen("poj3246.in","r",stdin);
17     freopen("poj3246.out","w",stdout);
18     //RQM 初始化,把log2(i),先打表出来 
19     //f[][]是以连续区间个数,不是n个 
20     while((scanf("%d%d",&n,&m))==2)
21     {
22         int i=1,q=2,p=0;
23     lo[i]=0;
24     while(i<=n)
25     {
26         i++;
27         if(i==q)
28         {
29             q*=2;
30             p++;
31         }
32         lo[i]=p;
33     }
34     int pre=N;
35     int k=0;
36     for(int i=1;i<=n;i++)//aa记录连续区间的起点中点个数 
37     {
38         scanf("%d",&a[i]);
39         if(a[i]!=pre)
40         {
41             k++;
42             aa[k].sta=i;
43             aa[k].end=i;//记录k的始末 
44             pre=a[i];
45         }
46         else aa[k].end=i;
47         pos[i]=k;//记录下标所对应的k 
48     }
49     for(int i=1;i<=k;i++)
50     aa[i].num=aa[i].end-aa[i].sta+1;
51     for(int i=1;i<=k;i++)
52     f[i][0]=aa[i].num; 
53     for(int j=1;j<=lo[n]+1;j++)
54     for(int i=1;i<=k;i++)
55     if(i+(1<<j)-1<=k)
56     f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);//分成等量两段长度为1<<j-1 
57     for(int i=1;i<=m;i++)
58     {
59         scanf("%d%d",&x,&y);
60         if(pos[x]==pos[y])cout<<y-x+1<<endl;
61         else 
62         {
63             int a1=aa[pos[x]].end;
64             int b1=aa[pos[y]].sta;
65             int n1=a1-x+1;
66             int n2=0;
67             int n3=y-b1+1;
68             int k1=pos[x],k2=pos[y];
69             int p=lo[k2-k1+1-2];//都是连续区间个数 
70             if(k2-k1-1==0)cout<<max(n1,n3)<<endl;
71             else
72             {
73                 n2=max(f[k1+1][p],f[k2-1-(1<<p)+1][p]);
74                 cout<<max(max(n1,n2),n3)<<endl;
75             }
76         } 
77     } 
78     }
79     return 0;
80 }

 总结:

1.RMQ求最值的用法

2,RMQ(线段树)的应用,不完全用,先分成三部分,中间一部分用RMQ

3,RMQ:f[i][j]初始化f[i][0]=a[i];

f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]),递推,for(j:1-log2(n))for(i:1-n)[j是外层循环,i是内层,先推两个的最大值,然后再是四个,八个]

4.看清题目,是多组数据

posted @ 2016-07-14 07:55  你笑不笑  阅读(883)  评论(0编辑  收藏  举报