码迷,mamicode.com
首页 > 编程语言 > 详细

hihoCoder #1068 : RMQ-ST算法

时间:2015-05-15 19:17:57      阅读:194      评论:0      收藏:0      [点我收藏+]

标签:

AC G++ 826ms 146MB

 

 

思路:

  按照提示一的方法进行实现。使用二进制的思想,只需要找到从第i个开始的2^j个数中的最小。i=(1,n)而因为n上限为100万,100万的二进制(1111 01000010 01000000),那么j 最大不超过20。按最坏情况算,只需要计算n*20个结果就行了,也就是O(n)。

  重点在如何在O(1)时间内计算pre[i][2^j]?利用二进制的性质,假如要计算pre[2][5](即长度为4),如果已经知道了pre[2][2]和pre[4][2],那么pre[2][5]=min(pre[2][2], pre[4][2]),两者刚好覆盖了从2~5。那么只需要按照j从小到大的顺序来计算每个i就行了。

  空间需要n*n?不需要了!第二维的2^j中的j不会超过20,那么二维中的3 5 6 7 9 10....这些都是没有记录东西的,很浪费空间。那么可以用j来作为二维索引,则第二维只需要20以上就行了。

  时间复杂度O(n+q)。这样算应该对吧?

 

技术分享
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N=1000100;
 4 int w[N], pre[N][32], n, q;
 5 void pre_cal()
 6 {
 7     for(int i=0; i<n; i++)    pre[i][0]=w[i];
 8     for(int i=2,q=1; i<=n; i*=2,q++)
 9         for(int j=0; j<n; j++)
10             if(j+i-1<n)    pre[j][q]=min(pre[j][q-1],pre[j+i/2][q-1]);
11             else    break;
12 }
13 int main()
14 {
15     //freopen("input.txt", "r", stdin);
16     cin>>n;
17     for(int i=0; i<n; i++)    scanf("%d",&w[i]);    //输入重量
18     pre_cal();    //预处理
19 
20     cin>>q;
21     int L, R;
22     for(int i=0; i<q; i++)  //输入查询,并直接处理输出
23     {
24         scanf("%d%d", &L, &R);
25         int len=R-L+1, tmp=0, cnt=0;
26 
27         for(int i=0; i<30; i++)//找出二进制最高位的1
28         {
29             if(!(len>>i))
30             {
31                 tmp=((len>>(i-1))<<(i-1));
32                 break;
33             }
34             cnt++;
35         }
36         if(R==L)    printf("%d\n",w[L-1]);
37         else if(tmp==len)    printf("%d\n",pre[L-1][cnt-1]);//这步其实可省。
38         else  printf("%d\n",min(pre[L-1][cnt-1], pre[R-tmp][cnt-1]));
39     }
40     return 0;
41 }
AC代码

 

hihoCoder #1068 : RMQ-ST算法

标签:

原文地址:http://www.cnblogs.com/xcw0754/p/4506423.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!