题目的意思是:有一个有序的数组,然后每次给出数组的两个端点L,R,要求出数组区间[L,R]里面出现最多的数字。
题目的解法:运用RMQ的思想求解即可,在求解之前需要转化一下模型,我们把这个数组可以转化为对于数字p,记录它的左端点位置nL[p],右端点位置nR[p],个数nV[p],对于每一次访问实际我们可以分三块来进行求解:首先是左端点num[L]的数字个数等于nR[num[L]] - L + 1,右端点的num[R]的数字个数等于R - nL[num[R]] + 1,然后中间的数字结果就用RMQ进行求解。
RMQ求解的主要代码块:
for(int i = 0; i < cN; i ++) A[i][0] = nV[num2[i]];
for(int j = 1; (1 << j) <= cN; j ++){
for(int i = 0; i + (1 << j) <= cN; i ++){
A[i][j] = max(A[i][j-1], A[i+(1 << (j - 1))][j - 1]);
}
}
<pre name="code" class="cpp"> ans = nR[num1[L]] - L + 1;
ans = max(R - nL[num1[R]] + 1, ans);
L = p[num1[L]] + 1, R = p[num1[R]] - 1;
if(L <= R){
int k = 0;
while((1 << (k + 1)) <= R - L + 1) k ++;
ans = max(ans, A[L][k]);
ans = max(ans, A[R + 1 - (1 << k)][k]);
}
#include "stdio.h"
#include "string.h"
#include "math.h"
#include <string>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <algorithm>
#include <iostream>
using namespace std;
#define MAXM 1
#define MAXN 1
#define max(a,b) a > b ? a : b
#define min(a,b) a < b ? a : b
#define Mem(a,b) memset(a,b,sizeof(a))
int Mod = 1000000007;
double pi = acos(-1.0);
double eps = 1e-6;
typedef struct{
int f,t,w,next;
}Edge;
Edge edge[MAXM];
int head[MAXN];
int kNum;
typedef long long LL;
void addEdge(int f, int t, int w)
{
edge[kNum].f = f;
edge[kNum].t = t;
edge[kNum].w = w;
edge[kNum].next = head[f];
head[f] = kNum ++;
}
map<int,int> nL, nR, nV;
map<int,int> p;
int n, cN, q;
int A[100005][20];
int num1[100005];
int num2[100005];
void solve(){
cin>>q;
for(int i = 0; i < n; i ++){
scanf("%d", &num1[i]);
}
nL.clear(), nR.clear(), nV.clear();
p.clear(), cN = 0;
Mem(A, 0);
int flag = false, pre = -1;
nL[num1[0]] = 1;
p[num1[0]] = cN ++;
num2[0] = num1[0];
for(int i = 1; i < n; i ++){
if(num1[i] != num1[i-1]){
nR[num1[i-1]] = i - 1;
nV[num1[i-1]] = nR[num1[i-1]] - nL[num1[i-1]] + 1;
//pre = num1[i];
num2[cN] = num1[i];
nL[num1[i]] = i;
p[num1[i]] = cN ++;
//flag = true;
}
}
nR[num1[n-1]] = n - 1;
nV[num1[n-1]] = nR[num1[n-1]] - nL[num1[n-1]] + 1;
for(int i = 0; i < cN; i ++) A[i][0] = nV[num2[i]];
for(int j = 1; (1 << j) <= cN; j ++){
for(int i = 0; i + (1 << j) <= cN; i ++){
A[i][j] = max(A[i][j-1], A[i+(1 << (j - 1))][j - 1]);
}
}
int L, R, ans;
for(int i = 0; i < q; i ++){
scanf("%d %d",&L, &R);
L -= 1, R -= 1;
if(num1[L] == num1[R]){
printf("%d\n", R - L + 1);
}
else{
ans = nR[num1[L]] - L + 1;
ans = max(R - nL[num1[R]] + 1, ans);
L = p[num1[L]] + 1, R = p[num1[R]] - 1;
if(L <= R){
int k = 0;
while((1 << (k + 1)) <= R - L + 1) k ++;
ans = max(ans, A[L][k]);
ans = max(ans, A[R + 1 - (1 << k)][k]);
}
printf("%d\n", ans);
}
}
}
int main()
{
// freopen("d:\\test.txt", "r", stdin);
while(cin>>n){
if(n == 0) break;
solve();
}
return 0;
}