题目链接: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代码:
1 #include<stdio.h> 2 #include<math.h> 3 int num[100010],f[100010],MAX[100010][20]; 4 int n; 5 int max(int a,int b) 6 { 7 return a>b?a:b; 8 } 9 void ST() 10 { 11 int i,j,k; 12 for(i=1;i<=n;i++) 13 MAX[i][0]=f[i]; 14 k=log((double)(n+1))/log(2.0); 15 for(j=1;j<=k;j++) 16 for(i=1;i+(1<<j)-1<=n;i++) 17 MAX[i][j]=max(MAX[i][j-1],MAX[i+(1<<(j-1))][j-1]); 18 } 19 int rmq_max(int l,int r) 20 { 21 if(l>r) 22 return 0; 23 int k=log((double)(r-l+1))/log(2.0); 24 return max(MAX[l][k],MAX[r-(1<<k)+1][k]); 25 } 26 int main() 27 { 28 int q,i,a,b; 29 while(scanf("%d",&n)&&n) 30 { 31 scanf("%d",&q); 32 for(i=1;i<=n;i++) 33 { 34 scanf("%d",&num[i]); 35 if(i==1) 36 { 37 f[i]=1; 38 continue; 39 } 40 if(num[i]==num[i-1]) 41 f[i]=f[i-1]+1; 42 else 43 f[i]=1; 44 } 45 ST(); 46 for(i=1;i<=q;i++) 47 { 48 scanf("%d%d",&a,&b); 49 int t=a; 50 while(t<=b&&num[t]==num[t-1]) 51 t++; 52 int cnt=rmq_max(t,b); 53 int ans=max(t-a,cnt); 54 printf("%d ",ans); 55 } 56 } 57 return 0; 58 }