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

【C++】RMQ问题

时间:2017-10-25 00:38:24      阅读:328      评论:0      收藏:0      [点我收藏+]

标签:href   强联通   printf   介绍   ini   范围   计算   max   遇到   

1.前言

范围最小/大值问题(Range Minimum/Maximum Query)也就是我们常说的RMQ。意思就是求出一个长度为n的数组A(A1,A2,……,An),求出一个范围(AL,AR)中的最小/大值。

2.思考

对于求范围最小值,我们可以用一个For循环来求:

1 int minval = 1000000000;//初始化min特别大
2 for(int i = l;i <= r;i++)
3     if(a[i] < minval) minval = a[i];
4 printf("%d\n",minval);

如果数据变态的话(多次询问且每次询问最长的区间),时间就长了。

再想一想,如果使用线段树维护区间最小值呢?线段树建树需要O(nlog(n)),查询需要O(log(n)),显然比上述第一种方法要快。但遇到数据变态时,你可以看看下面的例题,也会超时。我们需要一种更加快速的方法来解题。

3.ST表

很久以前,伟大的Tarjan教授(就是那个提出LCA,Link-Cut Tree[LCT],强联通分量的人)提出了计算RMQ问题的一种解法——Sparse-Table算法,就是我们现在常说的ST表,它预处理的时间为O(nlog(n)),相较于普通线段树(怕是有人会想起ZKW线段树),它的查询只需要O(1),并且,该算法的常数很小,更重要的是,它比普通线段树要好写的多。(PS:其实还有一种预处理时间为O(n)的算法—约束RMQ,但有些麻烦,暂时不介绍,感兴趣的同学可以自己查看)

不妨令d(i,j)表示从i开始的,长度为2i的一段元素的最小值,则我们可以用递推的方法计算d(i,j):d(i,j)=min{d(i,j-1),d(i+2j-1,j-1)},原理如下图所示。

 

【C++】RMQ问题

标签:href   强联通   printf   介绍   ini   范围   计算   max   遇到   

原文地址:http://www.cnblogs.com/water-mi/p/7726257.html

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