题意:
查询某个区间出现最多的数的次数
分析:
先预处理出这个节点左右两端的相同的数字的个数,然后根据每个点出现了多少次建立ST表,方便查询,将这段区间分成三段,进行计算。参考蓝书。
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
int arr[maxn];
int numl[maxn],numr[maxn];
int lg[maxn+10];
int ST[32][maxn];
void rmq_init(int n){
lg[0]=-1;
for(int i=1;i<=maxn;i++){
lg[i]=lg[i/2]+1;
}
for(int i=1;i<=n;i++){
ST[0][i]=numl[i]+numr[i]-1;
}
for(int i=1;i<=lg[n];i++){
for(int j=1;j+(1<<i)-1<=n;j++)
ST[i][j]=max(ST[i-1][j],ST[i-1][j+(1<<(i-1))]);
}
}
int solve(int l,int r){
int x=min(r-l+1,numr[l]);
int y=min(r-l+1,numl[r]);
l+=x,r-=y;
if(r<l) return max(x,y);
int t=lg[r-l+1];
return max(max(x,y),max(ST[t][l],ST[t][r-(1<<t)+1]));
}
int main(){
int n,m;
while(scanf("%d",&n)&&n){
scanf("%d",&m);
for(int i=1;i<=n;i++){
scanf("%d",&arr[i]);
numl[i]=numr[i]=1;
}
for(int i=2;i<=n;i++){
if(arr[i]==arr[i-1]){
numl[i]+=numl[i-1];
}
}
for(int i=n-1;i>=1;i--){
if(arr[i]==arr[i+1]){
numr[i]+=numr[i+1];
}
}
rmq_init(n);
while(m--){
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",solve(l,r));
}
}
return 0;
}