poj 3368(RMQ模板)

题目链接: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\n",ans);
55         }
56     }
57     return 0;
58 }
View Code

 

posted on 2013-09-06 21:38  jumpingfrog0  阅读(3396)  评论(2编辑  收藏  举报

导航