• 【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  } 
  • 相关阅读:
    idea maven 依赖还原不上的问题 method <init>()V not found
    QT6 发布程序
    Latex 公式缩放 Latex scales an equation to fit page width
    oracle使用dba账号查询死锁的表
    利用Vcpkg轻松集成开源第三方库
    python gdal 打包后运行exe Error:cannot find proj.db
    【GDAL】python读取DEM计算坡度与坡向
    docker启动关闭删除所有的容器命令
    用命令行编译libjpeg.lib
    mysql外键说明
  • 原文地址:https://www.cnblogs.com/hualian/p/11215613.html
Copyright © 2020-2023  润新知