POJ 3368 Frequent values 【ST表RMQ 维护区间频率最大值】

传送门:http://poj.org/problem?id=3368

Frequent values
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 23016   Accepted: 8060

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

Source

题意概括:

给出一串长度为 N 的非递减序列,和 M 次查询, 每次查询区间 【L,R】的出现频率最高的数的频率。

解题思路:

很妙的一种做法啊!

因为他是非递减数列 ,所以基于把每一个连续的相同的数作为同一块处理。

那么我们可以把查询区间分成两部分来处理。

第一部分:边界块,区间 起点 L 所处的块 和 区间 R 所处的块。

     如果两者所处的块相同则说明,该区间在一个块内,区间内的数都相同,那么我们所求的最大频率就是当前区间长度了

     如果两者所处的块不相同,那么说明除了这两个块还有其他的块,那么剩下的那些块就是接下来讨论的第二部分。

第二部分:很显然剩余的块都是连续的,完整的。那么RMQ维护的区间最大值妥妥的,没毛病(这里的最大值就是预处理的每一块的数出现的频率啦)。

AC code:

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cmath>
 5 #define INF 0x3f3f3f3f
 6 using namespace std;
 7 const int MAXN = 1e5+10;
 8 
 9 int num[MAXN];
10 int hh[MAXN];
11 int L[MAXN], R[MAXN];
12 int b[MAXN];
13 int dpmax[MAXN][20];
14 int mm[MAXN];
15 
16 void init_RMQ(int N, int a[])
17 {
18     mm[0] = -1;
19     for(int i = 1; i <= N; i++){
20         mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];
21         dpmax[i][0] = b[i];
22     }
23     for(int ilen = 1; ilen <= mm[N]; ilen++){
24         for(int i = 1; i+(1<<ilen)-1 <= N; i++)
25             dpmax[i][ilen] = max(dpmax[i][ilen-1], dpmax[i+(1<<(ilen-1))][ilen-1]);
26     }
27 }
28 
29 int get_RMQ(int LL, int RR)
30 {
31     int k = mm[RR-LL+1];
32     return max(dpmax[LL][k], dpmax[RR-(1<<k)+1][k]);
33 }
34 
35 int main()
36 {
37     int N, M;
38     while(~scanf("%d", &N) && N){
39         scanf("%d", &M);
40         for(int i = 1; i <= N; i++){
41             scanf("%d", &num[i]);
42         }
43 
44         int k = 1, ll = 1;
45         memset(b, 0 ,sizeof(b));
46 
47         for(int i = 1; i <= N; i++){
48             if(i > 1 && num[i] != num[i-1]){
49                 for(int j = ll; j < i; j++){
50                     L[j] = ll;
51                     R[j] = i-1;
52                 }
53                 b[k] = i-ll;
54                 ll = i;
55                 k++;
56             }
57             hh[i] = k;
58         }
59 
60         for(int j = ll; j <= N; j++){
61             L[j] = ll;
62             R[j] = N;
63         }
64         b[k] = N-ll+1;
65         init_RMQ(k, b);
66 
67         int U, V;
68         while(M--){
69             scanf("%d%d", &U, &V);
70             int st = hh[U], ed = hh[V];
71             if(st == ed){
72                 printf("%d
", V-U+1);
73                 continue;
74             }
75             int ans = max(R[U]-U+1, V-L[V]+1);
76             st++, ed--;
77             if(st <= ed) ans = max(ans, get_RMQ(st, ed));
78             printf("%d
", ans);
79         }
80     }
81     return 0;
82 }
View Code
原文地址:https://www.cnblogs.com/ymzjj/p/10035352.html