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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM