RMQ的应用,因为题目给定的数组相同的数字都是在一起,这意味着非常紧凑,借助RMQ,最值只可能有三种情况
- 频率最高是因为最左边的数
- 频率最高是因为最右边的数
- 将整个数组所有相同的数全部放在一个频数数组里面,所询问的区间内完整包含的那些数的频数最值可以利用RMQ来获取
#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdint>
#include <cassert>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
#include <deque>
#include <unordered_map>
using namespace std;
const int INF= 0x3f3f3f3f;
const int maxn= 1e5+5;
int n, q;
int a[maxn];
int L[maxn], R[maxn], idx[maxn];
int num[maxn];
int dv[maxn][20];
int lg[maxn];
void InitRMQ(int a[], int tot)
{
lg[0]= -1;
for (int i= 1; i <= tot; ++i){
lg[i]= i & (i-1) ? lg[i-1] : lg[i-1]+1;
dv[i][0]= a[i];
}
for (int j= 1; j <= lg[tot]; ++j){
for (int i= 1; i+(1<<j)-1 <= tot; ++i){
dv[i][j]= max(dv[i][j-1], dv[i+(1<<(j-1))][j-1]);
}
}
}
int RMQ(int l, int r)
{
if (l > r){
return 0;
}
int k= lg[r-l+1];
return max(dv[l][k], dv[r+1-(1<<k)][k]);
}
int main(int argc, char const *argv[])
{
while (~scanf("%d", &n) && n){
scanf("%d", &q);
for (int i= 1; i <= n; ++i){
scanf("%d", a+i);
}
int bg= 1, ed= 1;
int tot= 1;
for (int i= 1; i <= n; ++i){
if (a[i] != a[bg]){
ed= i-1;
for (int j= bg; j <= ed; ++j){
R[j]= ed;
}
num[tot]= i-bg;
++tot;
bg= i;
}
L[i]= bg;
idx[i]= tot;
}
ed= n;
for (int i= bg; i <= n; ++i){
R[i]= ed;
}
num[tot]= n+1-bg;
InitRMQ(num, tot);
int ans;
while (q--){
scanf("%d%d", &bg, &ed);
if (idx[bg] == idx[ed]){
ans= ed-bg+1;
} else{
ans= max(R[bg]+1-bg, ed+1-L[ed]);
ans= max(RMQ(idx[bg]+1, idx[ed]-1), ans);
}
printf("%d\n", ans);
}
}
return 0;
}