zoukankan      html  css  js  c++  java
  • 【基础算法-ST表】入门 -C++

    前言

    学了树状数组看到ST表模板跃跃欲试的时候发现完全没思路,因为给出的查询的时间实在太短了!几乎是需要完成O(1)查询。所以ST表到底是什么神仙算法能够做到这么快的查询?

    ST表

    ST表是一个用来解决RMQ问题(区间最值问题)的有效算法。
    它的功能也很简单。
    O(nlogn)预处理,O(1)查询区间最值。
    其他好像真还没什么用了

    算法

    ST表利用的是倍增的思路来实现的。
    怎么说呢,ST表确实很神奇。
    拿最大值来说吧...
    我们用f[i][j]表示第i个数开始的(2^j)个数中的最大值。
    p.s. 下面的图是这个大佬画的
    转移的时候我们可以把当前区间拆成两个区间并分别取最大值(注意这里的编号是从1开始的)

    查询也比较简单;
    首先要计算(log_2)(区间长度)
    然后分别查询左右段店,保证覆盖整个区间。
    在这里插入图片描述
    p.s因为我们需要找到一个点x使得(x+2^k-1=r),然后移项就可以得到(x=r-2^k+1),所以把x作为从右端点查询的区间的左端点,也就是(r-2^k+1)

    代码

    代码就比较好理解了...

    #include<bits/stdc++.h>
    using namespace std;
    inline int read()
    {
       int x=0,f=1;
       char ch=getchar();
       while(ch<'0'||ch>'9'){
           if(ch=='-')
               f=-1;
           ch=getchar();
       }
       while(ch>='0'&&ch<='9'){
           x=(x<<1)+(x<<3)+(ch^48);
           ch=getchar();
       }
       return x*f;
    }
    
    int f[100001][40],b,n,m,p,l,r;
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<=n;i++)
        	f[i][0]=read();
        b=(int)(log(n)/log(2));
        for(int j=1;j<=b;j++)
            for(int i=1;i<=n-(1<<j)+1;i++)
                f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
        for(int i=1;i<=m;i++) 
        {
            l=read(),r=read();
            p=(int)(log(r-l+1)/log(2));
            printf("%d
    ",max(f[l][p],f[r-(1<<p)+1][p]));
        }
        return 0;
    } 
    

    ov.

    个人博客地址: www.moyujiang.com 或 moyujiang.top
  • 相关阅读:
    VMware 中安装Centos
    go with go
    [APIO2012]派遣【左偏树】
    后缀自动机三·重复旋律6
    AC自动机(二次加强版)
    [HAOI2016]找相同字符【GSAM广义后缀自动机】
    吉司机线段树【学习笔记】
    [ZJOI2015]诸神眷顾的幻想乡【GSAM】
    广义后缀自动机(广义 SAM)【模板】
    Important Sisters【HDU-4694】【Dominator Tree】
  • 原文地址:https://www.cnblogs.com/moyujiang/p/11226303.html
Copyright © 2011-2022 走看看