//找序列 [a,b]之间出现频率最多的数,输出频率
//因为是有序序列所以,可以转化成RMQ,w[i] = num[i]累计出现次数
//然后找 [a,b]之间最大的w[i]就可以了
//考虑开头的情况,用st[i]存第一个num[i]的位置,ed[st[i]]存最后一个位置
//答案就是 max( w[ed[st[a]]] - w[a], rmqmax( ed[st[a]] + 1, b ) );
//注意下 ed[st[a]] 有没有超过b就可以了
//ST模板是百度百科的 =。=
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#define MN 100005
using namespace std;
//17 MN <= 2^17
int mi[MN][18],mx[MN][18],num[MN],w[MN], st[MN], ed[MN];
int n,q;
int a,b;
int LOG[MN];
void rmqinit()
{
int i,j,m;
for(i=1;i<=n;i++){mi[i][0]=mx[i][0]=w[i];}
m=floor(log((double)n)/log(2.0));
for(i=1;i<=m;i++)
{
for(j=n;j>=1;j--)
{
mx[j][i]=mx[j][i-1];
if(j+(1<<(i-1))<=n)mx[j][i]=max(mx[j][i],mx[j+(1<<(i-1))][i-1]);
mi[j][i]=mi[j][i-1];
if(j+(1<<(i-1)<=n))mi[j][i]=min(mi[j][i],mi[j+(1<<(i-1))][i-1]);
}
}
}
int rmqmin(int l,int r)
{
int m= LOG[r-l+1];
return min(mi[l][m],mi[r-(1<<m)+1][m]);
}
int rmqmax(int l,int r)
{
int m=LOG[r-l+1];
return max(mx[l][m],mx[r-(1<<m)+1][m]);
}
int main()
{
for( int i = 1;i < MN;i++ )
LOG[i] = floor( log( ( double )i ) / log( 2.0 )) ;
while( scanf( "%d",&n ) && n !=0 )
{
scanf( "%d%d",&q,num+1 );
w[1] = st[1] = 1;
for( int i = 2;i <= n;i++ )
{
scanf( "%d",num+i );
if( num[i] == num[i-1] )
{
w[i] = w[i-1] + 1;
st[i] = st[i-1];
}
else
{
ed[st[i-1]] = i-1;
w[i] = 1;
st[i] = i;
}
}
ed[st[n]] = n;
rmqinit();
for( int i = 1;i <= q;i++ )
{
scanf( "%d%d",&a,&b );
int mxx = w[ed[st[a]]] - w[a] + 1;
if( ed[st[a]] >= b )
{
mxx = w[b] - w[a] + 1;
}
else
{
int mxxx;
if( mxx < ( mxxx = rmqmax( ed[st[a]] + 1, b ) ) ) mxx = mxxx;
}
printf( "%d\n",mxx );
}
}
return 0;
}
POJ 3368 RMQ - ST
最新推荐文章于 2018-10-30 09:50:53 发布