zoukankan      html  css  js  c++  java
  • [OI学习笔记]st表

    用来查询区间最值(区间和,差等要处理重复部分)

    下面均以以最大值为例

    初始化 0(nlogn)

    设st[i][k]为下标i开始的2k个元素的最值

    则: st[i][k]=max{st[i][k-1],st[i+2k-1][k-1]}

    即区间[i,i+2k -1]的前一半和后一半的最值取最大

    查询 O(1)

    对于区间[l,r],区间长度len=r-l+1;找到满足2p <=len的最大p

    最大值ans=max{st[l][p],st[r-2p +1][p]} 

    显然,当2p !=len时,区间[l,l+p-1]和[r-2p +1][r]有重叠

    这也是为什么前面说区间和,差等要处理重复部分。

    2p <=len的p的最大值p <=log2len

    p=⌊log2len⌋  (下取整)

    代码:

    (注意第12行下标范围是i+(1<<k)-1<=n)

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    using namespace std;
    
    int st[100010][21],n;//st的第二维取到log2(10010)即可 
    
    void init(){
        for(int k=1;(1<<k)<=n;k++)
            for(int i=1;i+(1<<k)-1<=n;i++)
                st[i][k]=max(st[i][k-1],st[i+(1<<(k-1))][k-1]);
    }
    
    int ask(int l,int r){
        int len=r-l+1;
        //int p=(int)log((double)(len))/log(2.0);//满足2^p<=r-l+1的最大p
        int p=log2(len);
        return max(st[l][p],st[r-(1<<p)+1][p]); 
    }
    
    //以最大值为例 
    int main(){
        int m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d",&st[i][0]);
        init();
        for(int i=1;i<=m;i++){
            int l,r;
            scanf("%d%d",&l,&r);
            int ans=ask(l,r);
            printf("%d
    ",ans);
        }
        return 0;
    }
    本篇文章为SHINE_GEEK原创,转载请注明来源!
    written_by:SHINE_GEEK

    -------------------------------------
    签名:自己选的路,跪着也要走完;理想的实现,需要不懈奋斗!
    -------------------------------------
  • 相关阅读:
    表单元素的required,autocomplete,list用法
    通用triggerEvent方法
    通用addEventListener方法
    关于动态加载js
    Node路由简单的处理
    As3截图转换为ByteArray传送给后台node的一种方法
    JS中的“==”符号及布尔值转换规则
    解释JS变量作用域的范例
    .NET异步委托
    正则表达式入门
  • 原文地址:https://www.cnblogs.com/sjrb/p/10375723.html
Copyright © 2011-2022 走看看