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 andq (1 ≤ n, q ≤ 100000). The next line contains n integers a1, . . . , an (−100000 ≤ ai ≤ 100000, for eachi ∈ {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.
Note: A naive algorithm may not run in time!Sample Input
10 3
-1 -1 1 1 1 1 3 10 10 10 23
1 10
5 10
0
Sample Output
1 4 3
/*
这是一个有条件的区间出现次数查询, 相同的元素是放到一起的, 这简化了查询的操作.
用 Sparse Table 可以简单实现, 这种查询.
因为所有相同的元素是聚到一起的, 所以把相同的元素视作一个单元, 并给每一个单元编号.
这个单元的基本特征是最左端元素的位置, 最右端元素的位置, 元素的值和元素出现的次数(元素出现的次数可以用左右端点相减表示).
关于 Sparse Table 我的模版如下
查询操作的时间复杂度是 loglogn
预处理的时间复杂度是 nlogn
st表主要注意的地方是, 查询的二分要用upper_bound, 不能用 lower_bound
*/
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstdlib>
#include <cstdio>
#include <cmath>
const int MAXN = 1e5 + 600;
const int MAX_LOG2 = 20;
int st[MAXN][MAX_LOG2];
int bthPower[MAX_LOG2]; // 2th power, b == binary == 2
int _size;
void ST(int * a, int _n){
_size = _n;
bthPower[0] = 1;
for(int i = 1; i < MAX_LOG2; ++i){
bthPower[i] = bthPower[i - 1] << 1;
}
for(int i = 0; i < _size; ++i){
st[i][0] = a[i];
}
for(int j = 1; bthPower[j] <= _size; ++j){
for(int i = 0; i + bthPower[j] - 1 < _size; ++i){
st[i][j] = std::max(st[i][j - 1], st[i + bthPower[j - 1]][j - 1]);
}
}
}
int query(int lo, int hi){
int length = hi - lo + 1;
int power = std::upper_bound(bthPower, bthPower + MAX_LOG2, length) - bthPower - 1;
return std::max(st[lo][power], st[hi - bthPower[power] + 1][power]);
}
int cnt;
int value[MAXN], Count[MAXN], Left[MAXN], Right[MAXN];
int a[MAXN];
int n, q;
int lo, hi;
int main(){
while(scanf("%d", &n) && n){
cnt = 0; // 当前段的数量
scanf("%d", &q);
for(int i = 0; i < n; ++i){
scanf("%d", a + i);
}
// 先将第一个元素看作第一段, 简化处理
value[0] = a[0];
Count[0] = 1;
Left[0] = 0;
++cnt;
for(int i = 1; i < n; ++i){
if(a[i - 1] != a[i]){
Right[cnt - 1] = i - 1;
Left[cnt] = i;
Count[cnt] = 1;
value[cnt++] = a[i];
}
else{
++Count[cnt - 1];
}
}
// 假想的哨兵, 和最后一个元素不同
Right[cnt - 1] = n - 1;
ST(Count, cnt);
while(q--){
scanf("%d%d", &lo, &hi);
if(hi < lo){
std::swap(lo, hi);
}
// 这里可以用空间换时间, 在开一个编号数组, 记录每一个元素所在的段的编号.
int l = std::lower_bound(value, value + cnt, a[--lo]) - value; // 得到所在段的编号
int r = std::lower_bound(value, value + cnt, a[--hi]) - value;
if(l == r){
printf("%d\n", hi - lo + 1);
}
else if(l + 1 == r){ // 如果l, r在前后相邻的两端, 那么
printf("%d\n", std::max(hi - Left[r] + 1, Right[l] - lo + 1));
}
else{
int tmp = std::max(hi - Left[r] + 1, Right[l] - lo + 1);
int rst = query(l + 1, r - 1);
printf("%d\n", std::max(tmp, rst));
}
}
}
return 0;
}