zoukankan      html  css  js  c++  java
  • 【ST表(RMQ)】

    ST表

      ST表是一种解决RMQ(区间最值问题)的强有力的工具

      它可以做到O(nlogn)预处理,O(1)查询最值。

    实现

      ST表其实是一种倍增的思想,我们就拿取最大值为例:

    开一个二维数组Max,其中Max[i][j]表示从第i位开始,包括第i位在内的2^j个数中最大的数,例如Max[i][1]表示第i个数和第i+1个数中大的那个数。

     

    然后就类似于二分的样子,下一层也是拿两个已得到的区间的最大值作比较,然后存储。

    预处理代码

    1 for(int j=1;j<=21;j++)
    2     {
    3         for(int i=1;i+(1<<j)-1<=n;i++)
    4         {
    5             Max[i][j]=max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]);
    6         }
    7     }

      为什么要先循环j呢?因为我们是一层一层向上搜的,每一层的答案需要下面的基础,所以把j放在外层,然后(1<<(j-1))就是把二进制的1向左移动(j-1)位,也就是2^(j-1)。

    查询  

      查询也比较简单,我们只需要求出k=log2(r-l+1)(求2的k次幂小于这一段区间的值,并且尽可能大),然后得到两个区间,比较就行了

     (图片来源)

    然后取最大值返回就可以了

    1 int ST(int l,int r)
    2 {
    3     int k=log2(r-l+1);
    4     return max(Max[l][k],Max[r-(1<<k)+1][k]);
    5 }

    既然了解了这么多,不如.......(放心,都是模板题)

    洛谷P3865 【模板】ST表

     1 #include<bits/stdc++.h>
     2 #define N 100005
     3 using namespace std;
     4 int n,m;
     5 int Max[N][21];
     6 int ST(int l,int r)
     7 {
     8     int k=log2(r-l+1);
     9     return max(Max[l][k],Max[r-(1<<k)+1][k]);
    10 }
    11 int main()
    12 {
    13     cin>>n>>m;
    14     for(int i=1;i<=n;i++)
    15     {
    16         scanf("%d",&Max[i][0]);
    17     }
    18     for(int j=1;j<=21;j++)
    19     {
    20         for(int i=1;i+(1<<j)-1<=n;i++)
    21         {
    22             Max[i][j]=max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]);
    23         }
    24     }
    25     int l,r;
    26     for(int i=1;i<=m;i++)
    27     {
    28         scanf("%d%d",&l,&r);
    29         printf("%d
    ",ST(l,r));
    30     }
    31     return 0;
    32 }

    洛谷P2251 质量检测

     1 // luogu-judger-enable-o2
     2 #include<bits/stdc++.h>
     3 #define N 100005
     4 using namespace std;
     5 int n,m;
     6 int Min[N][21];
     7 int ST(int l,int r)
     8 {
     9     int k=log2(r-l+1);
    10     return min(Min[l][k],Min[r-(1<<k)+1][k]);
    11 }
    12 int main()
    13 {
    14     cin>>n>>m;
    15     for(int i=1;i<=n;i++)
    16     {
    17         scanf("%d",&Min[i][0]);
    18     }
    19     for(int j=1;j<=21;j++)
    20     {
    21         for(int i=1;i+(1<<j)-1<=n;i++)
    22         {
    23             Min[i][j]=min(Min[i][j-1],Min[i+(1<<(j-1))][j-1]);
    24         }
    25     }
    26     for(int i=1;i+m-1<=n;i++)
    27     {
    28         printf("%d
    ",ST(i,i+m-1));
    29     }
    30     return 0;
    31 }

    洛谷P1816 忠诚

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int Min[100005][21];
     4 int n,m;
     5 int ST(int l,int r)
     6 {
     7     int k=log2(r-l+1);
     8     return min(Min[l][k],Min[r-(1<<k)+1][k]);
     9 }
    10 int main()
    11 {
    12     cin>>n>>m;
    13     for(int i=1;i<=n;i++)
    14     {
    15         scanf("%d",&Min[i][0]);
    16     }
    17     for(int j=1;j<=21;j++)
    18     {
    19         for(int i=1;i+(1<<j)-1<=n;i++)
    20         {
    21             Min[i][j]=min(Min[i][j-1],Min[i+(1<<(j-1))][j-1]);
    22         }
    23     }
    24     for(int i=1;i<=m;i++)
    25     {
    26         int l,r;
    27         scanf("%d%d",&l,&r);
    28         printf("%d ",ST(l,r));
    29     }
    30  } 
  • 相关阅读:
    七牛图片上传JSSDK
    2015年12月中国航空公司名录
    HTML5 开发框架
    利用HTML5定位功能,实现在百度地图上定位
    openerp7 时区问题
    AS3使用Json 传复杂数据 -------- 用数组而不是向量
    随便写写
    生产环境该如何选择lvs的工作模式,和哪一种算法
    获取Linux权限后安装rootkit
    IT求职经验分享
  • 原文地址:https://www.cnblogs.com/hualian/p/11215613.html
Copyright © 2011-2022 走看看