数据结构(RMQ):UVAoj 11235 Frequent values

Frequent values

  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

  这题由于序列非降,所以就可以把整个数组进行游程编码(RLE Run Length Encoding)。
  还是很简单的~~~
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 const int maxn=100010;
 6 int mm[maxn],Max[maxn][30];
 7 int MAXL[maxn],MAXR[maxn],cnt=0;
 8 int ID[maxn],tot[maxn],a[maxn];
 9 void Init(){
10     memset(tot,0,sizeof(tot));
11     cnt=0;
12 }
13 int main(){
14 #ifndef ONLINE_JUDGE    
15     //freopen(".in","r",stdin);
16     //freopen(".out","w",stdout);
17 #endif
18     
19     int n,Q;
20     while(~scanf("%d",&n)&&n){
21         scanf("%d",&Q);
22         Init();
23         for(int i=1;i<=n;i++)
24             scanf("%d",&a[i]);
25         a[0]=a[n+1]=-212429368;
26         for(int i=1;i<=n;i++){
27             if(a[i]==a[i-1]){    
28                 MAXL[i]=MAXL[i-1];
29                 ID[i]=ID[i-1];
30             }
31             else{
32                 MAXL[i]=i;
33                 ID[i]=++cnt;
34             }
35             tot[ID[i]]++;
36         }
37         //MAXL[i]指与a[i]相等的1~i-1中最靠左的位置 
38         //ID[i]指当前位置被分到第几块
39         //tot[i]指第i块的长度 
40         for(int i=n;i>=1;i--){
41             if(a[i]==a[i+1])
42                 MAXR[i]=MAXR[i+1];
43             else 
44                 MAXR[i]=i;
45         }
46         //MAXR[i]指与a[i]相等的i+1~n中最靠右的位置 
47         mm[0]=-1;
48         for(int i=1;i<=cnt;i++){
49             mm[i]=(i&(i-1))?mm[i-1]:mm[i-1]+1;
50             Max[i][0]=tot[i];
51         } 
52         for(int k=1;k<=mm[cnt];k++)
53             for(int i=1;i+(1<<k)-1<=cnt;i++)
54                 Max[i][k]=max(Max[i][k-1],Max[i+(1<<(k-1))][k-1]);
55         //对块处理出稀疏表
56         int a,b,ans;
57         while(Q--){
58             scanf("%d%d",&a,&b);
59             if(a>b)swap(a,b);
60             if(ID[a]==ID[b]){
61                 printf("%d
",b-a+1);
62                 continue;
63             }
64             ans=-214748368;
65             ans=max(MAXR[a]-a+1,b-MAXL[b]+1);
66             a=ID[MAXR[a]+1];
67             b=ID[MAXL[b]-1];
68             if(a<=b)
69                 ans=max(ans,max(Max[a][mm[b-a+1]],Max[b-(1<<mm[b-a+1])+1][mm[b-a+1]]));
70             printf("%d
",ans);
71         }
72     }
73     return 0;
74 }
尽最大的努力,做最好的自己!
原文地址:https://www.cnblogs.com/TenderRun/p/5279405.html