zoukankan      html  css  js  c++  java
  • RMQ问题 ST算法(学习笔记)

    RMQ是询问某个区间的最大值或最小值的问题,主要求解方法之一ST算法;

    ST算法其实是倍增思想的产物,等下看代码实现就很明显了

    ST算法通常用在要多次询问一些区间的最值的问题中,相比于线段树,它的程序实现更简单,运行速度更快;

    ST算法没有修改操作(或者说不擅长动态修改)

    ST算法流程:

    预处理:ST算法的原理实际上是动态规划,我们用a数组表示一组数,设(f[i,j])表示从(a[i])(a[i+2^j-1])这个范围内的最大值,从中间平均分成两部分,即把(f[i,j])分为(f[i,j-1])(f[i+2^{j-1},j-1])(是不是很像倍增!!!)

    整个区间的最大值一定是左右两部分最大值的较大值,于是得到状态转移方程:

    (f[i][j]=max(f[i][j-1],f[i+2^{j-1}][j-1]))

    边界条件为(f[i][0]=a[i]);

    于是我们可以预处理出f数组;

    询问:若询问区间([l,r])的最大值,则先求出最大的x满足(2^x<=r-l+1),那么区间

    ([l,r]=[l,l+2^x-1]∪[r-2^x+1,r])

    两个区间有并集,但不妨碍求区间最值,这也是ST算法只能求区间最值的原因;

    求区间([x,y])的最大值,表达式为:

    (k=log_2(y-x+1));

    (ans=max(f[x][k],f[y-2^k+1][k]));

    因为log函数效率不高,通常递推预处理k值(设(log[d])表示(log_2)d向下取整,取(log[d]=log[d/2]+1)):

    
    log[0]=-1;//log[0]=-1,才能使log[1]=0
    for(int i=1;i<=n;i++)
    	log[i]=log[i>>1]+1;
        
    

    模板:

    
    log[0]=-1;
    for(int i=1;i<=n;i++)//n个数的序列
    	f[i][0]=a[i],log[i]=log[i>>1]+1;
    //根据f数组的定义,f[i][0]=a[i]
    //预处理出长度为1~n的log数组
    for(int j=1;j<=LogN;j++)//LogN一般取20即可
        for(int i=1;i+(1<<j)-1<=n;i++)//1<<j即2^j
            f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1])
    while(m--){
    	cin>>x>>y;//询问区间[x,y]内的最大值
        int k=log[y-x+1];//log2(y-x+1)向下取整的值
        cout<<max(f[x][k],f[y-(1<<k)+1][k]);
    }
    
    
  • 相关阅读:
    【代码笔记】iOS-判断是否是模拟机
    【代码笔记】iOS-拍照动画
    【代码笔记】iOS-轮询弹出框
    【代码笔记】iOS-iCarouselDemo
    【代码笔记】iOS-UIScrollerView里有两个tableView
    【代码笔记】iOS-两个时间字符串的比较
    【代码笔记】iOS-利用图片序列创建动态图片效果
    【代码笔记】iOS-离线地图
    【代码笔记】iOS-看图听声音
    【代码笔记】iOS-看图听故事
  • 原文地址:https://www.cnblogs.com/PPXppx/p/9898584.html
Copyright © 2011-2022 走看看