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 Specification
The input consists of several test cases. Each test case starts with a line containing two integers n and q (1 ≤ n, q ≤ 100000). The next line contains n integers a1 , ... , an (-100000 ≤ ai ≤ 100000, for each i ∈ {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 Specification
For each query, print one line with one integer: The number of occurrences of the most frequent value within the given range.
Sample Input
10 3
-1 -1 1 1 1 1 3 10 10 10
2 3
1 10
5 10
0
Sample Output
1
4
3
A naive algorithm may not run in time!
题意:
给出一个非降序的整数数组,你的任务是对于一系列询问,回答区间内出现最多的值的次数
首先要知道什么是RMQ问题
思路:
因为这个数组是非降序的,所以可以把所有相等的元素组合起来用二元组表示,例如-1,1,1,2,2,2,4就可以表示为(-1,1)(1,2)(2,3)(4,1),其中(a,b)代表有b个连续的a。
首先将其分段来解决,否则不能套用ST的板子
因此这里用cnt[i]代表当前编号i段的长度,L[i]表示编号为i的段的左端点的位置,R[i]表示编号为i的段的右端点的位置,num[i]表示i这个位置的编号
#include<iostream>
#include<set>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define mem(a,b) memset(a,b,sizeof a);
const int N = 1e5+7;
const int INF=0x3f3f3f3f;
const int P=1e5;
int a[N];
int num[N<<1];
int cnt[N<<1];
int L[N<<1];
int R[N<<1];
int dp[N][43];
void Init(){
mem(dp,0);//mem(val,0);
mem(num,0);mem(cnt,0);
mem(L,0);mem(R,0);
}
void RMQ(int n){
rep(i,1,n) dp[i][0]=cnt[i];
for(int j=1;(1<<j)<=n+1;j++){
for(int i=1;i+(1<<j)-1<=n;i++)
dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
}
int query(int l,int r){
int k=0;
while((1<<(k+1))<=r-l+1) k++;
return max(dp[l][k],dp[r-(1<<k)+1][k]);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
int n,q;
while(scanf("%d",&n)!=EOF,n){
Init();
scanf("%d",&q);
scanf("%d",&a[1]);
int len=1;
cnt[len]++;
num[1]=len;
// L[0]=1;
rep(i,2,n) {
scanf("%d",&a[i]);
if(a[i]==a[i-1]){
cnt[len]++;
num[i]=len;
}else{
R[len]=i-1;
len++;
cnt[len]=1;
num[i]=len;
L[len]=i;
}
}
RMQ(len);
while(q--){int x,y;
scanf("%d%d",&x,&y);
if(num[x]==num[y]){//如果只有一种
printf("%d\n",y-x+1);
}else{
int ans=0;
if(num[x]+1<=num[y]-1)//如果小于两种就不用RMQ了
ans=query(num[x]+1,num[y]-1);
ans=max(ans,max(R[num[x]]-x+1,y-L[num[y]]+1));
printf("%d\n",ans);
}
}
}
return 0;
}