题目链接:http://poj.org/problem?id=3368
题意:给出n个数和Q个询问(l,r),对于每个询问求出(l,r)之间连续出现次数最多的次数。
求解RMQ问题的算法有:搜索(比较暴力),线段树,ST算法(DP),其中较为高效的是ST算法,比较常用,
复杂度:预处理O(nlogn),查询O(1)。
RMQ算法(ST)请参考:http://blog.csdn.net/liang5630/article/details/7917702
分析:将原序列转换一下,if(num[i]==num[i-1])
f[i]=f[i-1]+1;
else
f[i]++;
对于每个询问(l,r),分为两个部分,前半部分求与l之前相同的数的个数直到t,后半部分从t开始直接用RMQ求解最大值就行了。
最后结果为max(前半部分,后半部分)。
AC代码:
#include<stdio.h>
#include<math.h>
int num[],f[],MAX[][];
int n;
int max(int a,int b)
{
return a>b?a:b;
}
void ST()
{
int i,j,k;
for(i=;i<=n;i++)
MAX[i][]=f[i];
k=log((double)(n+))/log(2.0);
for(j=;j<=k;j++)
for(i=;i+(<<j)-<=n;i++)
MAX[i][j]=max(MAX[i][j-],MAX[i+(<<(j-))][j-]);
}
int rmq_max(int l,int r)
{
if(l>r)
return ;
int k=log((double)(r-l+))/log(2.0);
return max(MAX[l][k],MAX[r-(<<k)+][k]);
}
int main()
{
int q,i,a,b;
while(scanf("%d",&n)&&n)
{
scanf("%d",&q);
for(i=;i<=n;i++)
{
scanf("%d",&num[i]);
if(i==)
{
f[i]=;
continue;
}
if(num[i]==num[i-])
f[i]=f[i-]+;
else
f[i]=;
}
ST();
for(i=;i<=q;i++)
{
scanf("%d%d",&a,&b);
int t=a;
while(t<=b&&num[t]==num[t-])
t++;
int cnt=rmq_max(t,b);
int ans=max(t-a,cnt);
printf("%d\n",ans);
}
}
return ;
}