题意:
给出非降序整数列,q次查询区间内出现次数最多的值所出现的次数
思路:
利用游程编码的得到新数列A[],然后对A进行RMQ,每次查询区间[ l , r ] ,分成三个部分,[ l , right[ l ] ] , [ l+1 , r-1 ] ,[ left [ r ] , r ] 。游程编码竞赛好像蛮实用,可以借这题熟悉一下。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
namespace Sparse_Table
{
const int MAX_N = 1e5+5;
int n;int e[MAX_N];
int A[MAX_N];/**从0开始存储序列**/
int d[MAX_N][24];
int right[MAX_N][24];
int left[MAX_N][24];
void ST_init(){
for(int i=0;i<n;i++){
d[i][0] = A[i];
if(i){
left[i][0] = right[i-1][0]+1;
right[i][0] = left[i][0] + A[i] - 1;
}
else {
left[i][0]=0;
right[i][0]=A[i]-1;
}
}for(int j=1;(1<<j)<=n;j++){
for(int i=0;i+(1<<j)-1 < n ;i++){
d[i][j] = max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
right[i][j] = right[i+(1<<(j-1))][j-1];
left[i][j] = left[i][j-1];
}
}
}
int ST(int L,int R){
int a = e[L] , b = e[R];
if(a==b)return R-L+1;
int res = max( right[a][0]-L+1 , R-left[b][0]+1 );
int k=0;a++;b--;
if(a<=b){
while((1<<(k+1)) <= b-a+1)k++;
res = max( res , max(d[a][k],d[b-(1<<k)+1][k]) );
}return res;
}
}
using namespace Sparse_Table;
int main()
{
int q;
while(scanf("%d",&n)==1&&n)
{
scanf("%d",&q);
int last=1e7,nn=0;
for(int i=0,now;i<n;i++){
scanf("%d",&now);
if(now==last){
A[nn-1]++;
}else {
A[nn++]=1;
last = now;
}e[i]=nn-1;
}
n = nn;
ST_init();
int L,R;
while(q--){
scanf("%d%d",&L,&R);
printf("%d\n",ST(L-1,R-1));
}
}
}