1. 程式人生 > >POJ 3368 Frequent values 【ST表RMQ 維護區間頻率最大值】

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

Ulm Local 2007

 

 

題意概括:

給出一串長度為 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\n", 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\n", ans);
79         }
80     }
81     return 0;
82 }
View Code