标签:href 强联通 printf 介绍 ini 范围 计算 max 遇到
范围最小/大值问题(Range Minimum/Maximum Query)也就是我们常说的RMQ。意思就是求出一个长度为n的数组A(A1,A2,……,An),求出一个范围(AL,AR)中的最小/大值。
对于求范围最小值,我们可以用一个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)),显然比上述第一种方法要快。但遇到数据变态时,你可以看看下面的例题,也会超时。我们需要一种更加快速的方法来解题。
很久以前,伟大的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)},原理如下图所示。
标签:href 强联通 printf 介绍 ini 范围 计算 max 遇到
原文地址:http://www.cnblogs.com/water-mi/p/7726257.html