zoukankan      html  css  js  c++  java
  • RMQ问题

    解决RMQ(Range Minimum/Maximum Query)即区间最大最小值问题。

    有一个离线算法(ST算法),这个算法是很高效了,时间是O(nlogn):(用O(nlogn)的时间进行预处理,再用O(1)的时间进行区间查询)

    1.先是预处理(用动态规划解决)

     A数列为:3 2 4 5 6 8 1 2 9 7

    F[1,0]表示第1个数起,长度为2^0=1的最大值,其实就是3这个数。同理 F[1,1] = max(3,2) = 3, F[1,2]=max(3,2,4,5) = 5,F[1,3] = max(3,2,4,5,6,8,1,2) = 8;

    首先,DP的初始值,即第一次时,每次都是自己本身:F[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     //初始化
     4     for (int i = 1; i <= num; i++){
     5         minsum[i][0] = a[i];
     6         maxsum[i][0] = a[i];
     7     }
     8 
     9     for (int j = 1; j < 25; j++)
    10     for (int i = 1; i <= num; i++)
    11     if (i + (1 << j) - 1 <= num)
    12     {
    13         maxsum[i][j] = max(maxsum[i][j - 1], maxsum[i + (1 << (j - 1))][j - 1]);
    14         minsum[i][j] = min(minsum[i][j - 1], minsum[i + (1 << (j - 1))][j - 1]);
    15     }
    16 }

    其中 i 和 j 的位置不能变,因为是先更新 1 个元素,再更新两个,四个.....等元素,以此类推更新所有长度的最值。

    2.查询

     1 //查询
     2 int getmin(int x, int y){
     3     int k = (int)(log((double)(y - x + 1)) / log(2.0));
     4     return min(minsum[x][k], minsum[y - (1 << k) + 1][k]);
     5 }
     6 
     7 int getmax(int x, int y){
     8     int k = (int)(log((double)(y - x + 1)) / log(2.0));
     9     return max(maxsum[x][k], maxsum[y - (1 << k) + 1][k]);
    10 }

    对于需要查询的区间[ x, y],区间的差值为 len = y - x + 1;

    那么查询的时候 设此时的 j 是 k,那么在查询时,需要 x -- x + 2^k -1 和 y - 2^k + 1 -- y之间,此时就要找到合适的K值。

    1 int k=0;  
    2     while((1<<(k+1))<=y-x+1)  
    3         k++;  

    用这个方法找也可以,不过有个更快捷的 k=log2( y - x + 1) 直接进行取值。

  • 相关阅读:
    VS2013 使用QCustomPlot等三方库如何配置
    error LNK1112:模块计算机类型"X64" 与目标计算机类型"X86" 冲突
    Qt 获取屏幕当前分辨率
    流程控制
    导航条和工作内容纪要
    js简介
    高度塌陷
    浮动
    文档流
    display和overflow
  • 原文地址:https://www.cnblogs.com/ouyang_wsgwz/p/7811230.html
Copyright © 2011-2022 走看看