zoukankan      html  css  js  c++  java
  • 【模板】ST表

    给定一个长度为 (N) 的数列,和 (M) 次询问,求出每一次询问的区间([l,r])内数字的最大值。

    说明
    对于30%的数据,满足: (1 leq N, M leq 10 , 1≤N,M≤10)
    对于70%的数据,满足: (1 leq N, M leq {10}^5 , 1≤N,M≤10^5)
    对于100%的数据,满足: (1 leq N leq {10}^5, 1 leq M leq {10}^6, a_i in [0, {10}^9], 1 leq l_i leq r_i leq N 1≤N≤10^5 ,1≤M≤10^6,a i ∈[0,10^9],1≤l i ≤r i​ ≤N)

    思路

    1.(O(n))暴力枚举

    左转右转都可以 详情见数据范围

    2.线段树(O(logn))

    左转右转都可以 详情见数据范围


    所以呢,我们需要一个(O(1))的查询效率。

    3.区间动规

    记录(f(i,j))为区间([i,j])的最大值。

    转移(f(i,j)=max(f(i,j−1),a[j]))

    然而这需要(O(n^2))的预处理。

    左转右转都可以 详情见数据范围

    4.ST表

    其实这是个经典的ST表模板。静态区间最值。

    和LCA一样,都用到了倍增的思路。

    我们令(f(i,j)) 为从(a[i])开始的,连续 (2^j)个数的最大值

    于是我们有(f(i,0)=a[i])(多显然啊qwq)

    于是我们还有(f(i,j)=max(f(i,j-1),f(i+2^{j-1},j-1)))

    我太懒了不想证怎么办(画个图膜你一下就行了)

    对于查询,根据(max) 的性质,我们可以把区间拆成两个相重叠的区间。

    于是按照预处理来推一下就得到,查询区间([left,right])

    (len=log2(right-left+1))
    (max(f[left][len-1],f[right-(1<<(len-1))+1][len-1])))

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define MAXN 100005
    #define len lg[right-left+1]
    #define scan(a) scanf("%d",&a)
    #define print(a) printf("%d",a)
    #define printn(a) printf("%d
    ",a)
    #define printwn(a) printf("%d ",a)
    #define endl printf("
    ")
    using namespace std;
    int n,m,a[MAXN],lg[MAXN],maxx[MAXN][25];
    
    int main()
    {
        scan(n); scan(m);
        for (int i=1;i<=n;i++)
        {
            lg[i]=lg[i/2]+1;
        }
        for (int i=1;i<=n;i++)
        {
            scan(a[i]);
        }
        for (int i=1;i<=n;i++)
        {
            maxx[i][0]=a[i];
        }
        for (int i=1;i<=lg[n];i++)
        {
            for (int j=1;j+(1<<i)-1<=n;j++)
            {
                maxx[j][i]=max(maxx[j][i-1],maxx[j+(1<<(i-1))][i-1]);
            }
        }
        int left,right;
        for (int i=1;i<=m;i++)
        {
            scan(left); scan(right);
            printn(max(maxx[left][len-1],maxx[right-(1<<(len-1))+1][len-1]));
        }
        return 0;
    }
    
  • 相关阅读:
    升级windows 11小工具
    windows 10更新升级方法
    您需要了解的有关 Oracle 数据库修补的所有信息
    Step by Step Apply Rolling PSU Patch In Oracle Database 12c RAC Environment
    Upgrade Oracle Database Manually from 12.2.0.1 to 19c
    如何应用版本更新 12.2.0.1.210420(补丁 32507738 – 2021 年 4 月 RU)
    xtrabackup 安装、备份和恢复
    Centos_Lvm expand capacity without restarting CentOS
    Centos_Lvm_Create pv vg lv and mount
    通过全备+relaylog同步恢复被drop的库或表
  • 原文地址:https://www.cnblogs.com/Kan-kiz/p/10697425.html
Copyright © 2011-2022 走看看