题目大意:
给出一个非降序排列的整数数组,对于每组询问 (l, r),给出区间 [l, r] 中出现次数最多的值的出现次数
根据题意,整个数组非降序排列,那么相同的数都会凑在一起
这样我们对于每个位置记录 3 个值:tol, tor, tot
分别代表:
和这个数相同的值向左最远延伸到 tol
和这个数相同的值向右最远延伸到 tor
和这个数相同的数共有 tot 个
这样我们就可以根据以上三个值和下标愉快的打ST表了
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cstdio>
using namespace std;
const int MAXN = 100005;
int n, q;
int a[MAXN], tol[MAXN], tor[MAXN], tot[MAXN], st[MAXN][30];
inline void ST_init() {
for(int i = 1; i <= n; ++i) st[i][0] = tot[i];
for(int j = 1; (1 << j) <= n; ++j)
for(int i = 1; i + (1 << j) - 1 <= n; ++i)
st[i][j] = max(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
return;
}
inline int query(int l, int r) {
if(a[l] == a[r]) return r - l + 1;
int res = -100001, k = 0;
res = max(res, max(tor[l] - l + 1, r - tol[r] + 1));
l = tor[l] + 1;
r = tol[r] - 1;
if(l > r) return res;
while((1 << (k + 1)) <= r - l + 1) ++k;
return max(res, max(st[l][k], st[r - (1 << k) + 1][k]));
}
inline void resetall() {
memset(a, 0, sizeof(a));
memset(tol, 0, sizeof(tol));
memset(tor, 0, sizeof(tor));
memset(tot, 0, sizeof(tot));
memset(st, 0, sizeof(st));
return;
}
int main() {
while(scanf("%d", &n) and n) {
scanf("%d", &q);
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
int totk = 0, rk = n, rnk = 0, k = 0;
for(int i = 1; i <= n + 1; ++i) {
if(a[i] != a[i - 1]) {
int j = i - 1;
while(j and !tot[j]) {
tot[j--] = totk;
}
totk = 0;
}
++totk;
}
ST_init();
for(int i = 1; i <= n; ++i) {
if(a[i] != a[i - 1]) k = i;
tol[i] = k;
int rvrs = n - i + 1;
if(a[rvrs] != a[rvrs + 1]) rk = rvrs;
tor[rvrs] = rk;
}
int l, r;
while(q--) {
scanf("%d%d", &l, &r);
if(a[l] == a[r]) printf("%d\n", r - l + 1);
else printf("%d\n", query(l ,r));
}
resetall();
}
return 0;
}