• 【学习】ST表!


    Pre-Scene

    我们有一道小水题

    给出一个长度为n的序列,m次询问,每次询问区间内的最大值

    有大佬说,线段树秒切

    ST表...神秘的大佬在角落里出声…

    什么!大佬们回头喊道

                                                                                                                                                                                                             

    关于ST表

    确实,关于求区间最值,线段树已经很nice了,但是,对于静态区间最值,我们还有更优秀的——ST表

    其预处理复杂度为O(log n),而查询是O(1)的!

    对于离线的题目,用码量少不易出错(我写线段树从没一遍过过)且较快的ST表,是更优的

    原理  

    以一种类似于二分的思想,把要查询的区间分成两个小区间分别查询最值,由小区间找到大区间的最小值

    算法实现

    最值是通过一个 st[i][j] 数组来储存的

    st[i][j] 是存的从 i 开始的 2^j 个数中的最大值,即区间[ i , i+2^j ) 的最值

    预处理

    void chuli(){
      for(int j=1;j<=21;j++)         //j<=21是因为题目数据在1e6内
         for(int i=1;i+(1<<j)-1<=n;i++){     //区间[i,i+2^j)
            st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);  //区间[i,i+2^j)的最值由[i,i+2^(j-1))和[i+2^(j-1),i+2^j)转移过来  
        }
    }

    来画个图理解下

    根据初中数学知识,易得 i+2^(j-1) 是这段区间的中点(这里呼应了上文的二分思想)

    这样我们就把一段较长的区间分成了两个小区间,再取两个小区间最值的最值,即可得到大区间的最值

    查询

    int qurey(int l,int r){
        int k=log2(r-l+1);       //求出 log2(区间长度),这样可以保证一定可以覆盖要查询的区间
        return max(st[l][k],st[r-(1<<k)+1][k]);  //此处将 k 带入即可轻松理解
    }

    为什么能保证一定可以覆盖呢?再来张图

    对于左右端点分别查询,就保证了区间被完全覆盖

    洛谷板子P3865 传送门

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int st[100005][21];
    int n,m;
    int qurey(int l,int r){
        int k=log2(r-l+1);
        return max(st[l][k],st[r-(1<<k)+1][k]);
    }
    void chuli(){
      for(int j=1;j<=21;j++)
       for(int i=1;i+(1<<j)-1<=n;i++){
          st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&st[i][0]);   //想一想,为什么这么输入
        }
       chuli();
    for(int i=1;i<=m;i++){ int l,r; scanf("%d%d",&l,&r); printf("%d ",qurey(l,r)); } return 0; }

     后记:自从小蒟蒻发现了ST表这种好用的东西,静态区间最值再没写过线段树 (*^__^*) 

              pre-scene里的小水(S)题(T),其实已经说明了这题的做法 O(∩_∩)O~

  • 相关阅读:
    JQ 放大镜
    Jquery.tmpl
    Jquery Live方法
    Bootstrap之底层媒体查询
    Bootstrap 字体与图标
    工具提示
    模态框
    BootStrap格栅系统
    Tab选项卡
    弹出框
  • 原文地址:https://www.cnblogs.com/gengyf/p/10802805.html
Copyright © 2020-2023  润新知