RMQ模版总结

相关链接:http://blog.csdn.net/niushuai666/article/details/6624672

简介:RMQ有点像线段树,预处理的时间复杂度是nlogn,每次询问为O(1),所以,对于多次查找值不变的区间最大最小值具有非常高的效率。

相关变量:a数组,maxsum数组代表最大值,minsum代表最小值。

maxsum[i][j]的含义:从i开始。连续2^j个元素的最大值。比如,[1,0] ,代表从i=1开始,2^0=1个元素,也就是1,1 最大值即本身。

初始化:

注意一点,从1到n还是从0到n-1

将maxsum[i][0] = minsum[i][0] = a[i];

然后状态转移方程:状态转移方程F[i, j]=max(F[i,j-1], F[i + 2^(j-1),j-1])。

代码:

 1 void RMQ(int num) //预处理->O(nlogn)
 2 {
 3     for(int i=1;i<=num;i++)
 4        maxsum[i][0] = minsum[i][0] = a[i];
 5     for(int j = 1; j < 20; ++j)
 6         for(int i = 1; i <= num; ++i) //如果是从0~n-1,这里i的循环变成从0~num-1;
 7             if(i + (1 << j) - 1 <= num)
 8             {
 9                 maxsum[i][j] = max(maxsum[i][j - 1], maxsum[i + (1 << (j - 1))][j - 1]); //加小括号因为+-优先级高
10                 minsum[i][j] = min(minsum[i][j - 1], minsum[i + (1 << (j - 1))][j - 1]);
11             }
12 }

状态转移的实质:倍增。

查询代码:

1 int query(int l,int r)
2 {
3         int k=0;
4         while((1<<(k+1))<(r-l+1))
5                 k++;
6         int MIN=min(minsum[l][k],minsum[r-(1<<k)+1][k]);
7         int MAX=max(maxsum[l][k],maxsum[r-(1<<k)+1][k]);
8         return t-tt; //最大和最小差值
9 }

部分代码参考:飘过的小牛

posted on 2015-07-22 14:11  小松song  阅读(113)  评论(0)    收藏  举报

导航