题意:给出一串非下降数字,然后给出若干个询问区间,求区间内数字出现最多的次数。
思路:lrj白书上的一道不错的RMQ题,看了书的分析然后顺手切了下,解决这道题可以抓住数列非下降这个条件,也就是每个数字都有他的出现区间。我们用数组L[i],R[i]分别记录第i个数字最先出现和最后出现的位置。用数组cnt[i]来记录第i个数字出现的次数,然后对cnt数组(其实是maxArr[i][0])进行RMQ;每次询问q区间left,right,将这个问题分成三部分,首先求出第left位置的数字最后出现的位置,即R[l],出现的次数为R[l] - l + 1,然后求出right位置的数字最先出现的位置,即L[r],出现的次数r - L[r] + 1,去除了左右两边可能不完整的区间后,然后就可以对剩余的那个区间进行RMQ了,答案就是这三部分的最大值。
注意特殊情况,如果第left位置的数字等于第right位置的数字,则直接输出r - l + 1;
这道题的要点是要单独处理不完整的区间,然后rmq完整的区间。
#include <set>
#include <map>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <climits>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define pub push_back
#define inst insert
#define mp make_pair
#define SZ(x) ((int)(x).size())
#define ForEach(i,c) for(__typeof((c).begin()) i = (c).begin();i != (c).end();i++)
using namespace std;
const int N = 100010;
const int M = 35;
const int INF = 123456789;
int val[N], maxArr[N][M];
int L[N], R[N], sta[N], n, q;
inline int max(int a, int b){
return a > b?a:b;
}
void makeRMQ(){
int l = (int)(log((double)n) / log(2.0));
for (int j = 1;j <= l;j++)
for (int i = 1; i + (1 << (j - 1) ) - 1 <= n;++i)
maxArr[i][j] = max(maxArr[i][j - 1], maxArr[i + (1 << (j - 1))][j - 1]);
}
int rmq(int l, int r){
int k = (int)(log((double)(r - l + 1)) / log(2.0));
int Max = max(maxArr[l][k], maxArr[r - (1 << k) + 1][k]);
return Max;
}
void work(){
int i, top = 0, idx;
sta[n + 1] = sta[0] = 0;
val[0] = INF;
for(i = 1;i <= n + 1;i++){
if(val[sta[top]] != val[i]){
while(top)
R[sta[top--]] = i - 1;
idx = i;
sta[++top] = i;
}else
sta[++top] = i;
L[i] = idx;
}
for(i = 1;i <= n;i++)
maxArr[i][0] = R[i] - L[i] + 1;
makeRMQ();
}
int main(){
while(cin >> n){
if(n == 0)
return 0;
int i, l, r;
cin >> q;
for(i = 1;i <= n;i++){
scanf("%d", &val[i]);
}
work();
while(q--){
scanf("%d%d", &l, &r);
int res = R[l] - l + 1;
res = max(res, r - L[r] + 1);
if(L[l] == L[r])
cout << r - l + 1 << endl;
else if(R[l] + 1 <= L[r] - 1)
printf("%d\n", max(res , rmq(R[l] + 1, L[r] - 1)));
else
printf("%d\n", res);
}
}
return 0;
}