【算法模板】数据结构:ST表

【算法模板】数据结构:ST表

概念

ST 表是一种基于 倍增 思想,用于解决 可重复贡献问题 的数据结构

可重复贡献问题 是指对于运算 opt⁡opt,满足 𝑥opt⁡𝑥=𝑥x optx =x ,则对应的区间询问就是一个可重复贡献问题。例如,最大值有 max⁡(𝑥,𝑥)=𝑥max(x ,x )=x ,gcd 有 gcd⁡(𝑥,𝑥)=𝑥gcd(x ,x )=x,所以 RMQ 和区间 GCD 就是一个可重复贡献问题。像区间和就不具有这个性质,如果求区间和的时候采用的预处理区间重叠了,则会导致重叠部分被计算两次,这是我们所不愿意看到的。另外,opt⁡opt 还必须满足结合律才能使用 ST 表求解。

ST 表基于倍增 思想,可以做到 𝑂(n logn) 预处理,O*(1) 回答每个询问。但是不支持修改操作。

所谓预处理,即我们需要预先处理出,对于每个位置 i,我们需要知道,以 i 作为左端点, i+2^j-1作为右端点的每个区间的最大值。

由于 log2n 较小,所以我们可以直接枚举每个 j。

我们用一个数组表示,f[i][j] 表示以 i 为左端点,区间长度为2^j ,也就是右端点是 i+2^j-1。

模板

cpp 复制代码
vector<vector<int>> ST_prework(const vector<int> &v) {
    int n = v.size();
    int t = log2(n)+1;
    vector<vector<int>> ST(n, vector<int>(t));
    for (int i = 0; i < n; i++)ST[i][0] = v[i];
    for (int j = 1; j < t; j++)//枚举区间长度
        for (int i = 0; i + (1 << j) - 1 < n; i++)
            ST[i][j] = max(ST[i][j - 1], ST[i + (1 << (j - 1))][j - 1]);
    return ST;
}
int ST_query(vector<vector<int>> &ST,int l, int r) {
    int k = log2(r - l + 1);//左闭右闭
    return max(ST[l][k], ST[r - (1 << k) + 1][k]);
}

例题

区间最大值

区间最大值 - 蓝桥云课 (lanqiao.cn)

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
int main() {
    int n,q;cin>>n>>q;
    const int t=log2(n)+1;
    vector<vector<int>> st(n,vector<int>(t));
    for(int i=0;i<n;i++)cin>>st[i][0];
    for(int i=1;i<t;i++)
        for(int j=0;j+(1<<(i-1))<n;j++)
            st[j][i]=max(st[j][i-1],st[j+(1<<(i-1))][i-1]);
    while(q--){
        int l,r;cin>>l>>r;
        l--,r--;
        int x=log2(r-l+1);
        cout<<max(st[l][x],st[r-(1<<x)+1][x])<<endl;
    }
    return 0;
}

Balanced Lineup G

USACO07JAN Balanced Lineup G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
int main() {
    int n, q;
    cin >> n >> q;
    const int t = log2(n) + 1;
    vector<vector<int>> stmax(n, vector<int>(t));
    for (int i = 0; i < n; i++)cin >> stmax[i][0];
    auto stmin = stmax;
    for (int j = 1; j < t; j++) {
        for (int i = 0; i + (1 << (j - 1)) < n; i++) {
            stmax[i][j] = max(stmax[i][j - 1], stmax[i + (1 << (j - 1))][j - 1]);
            stmin[i][j] = min(stmin[i][j - 1], stmin[i + (1 << (j - 1))][j - 1]);
        }
    }
    while(q--){
        int a,b;cin>>a>>b;
        --a,--b;
        int x=log2(b-a+1);
        int ans=0;
        ans+=max(stmax[a][x],stmax[b-(1<<x)+1][x]);
        ans-=min(stmin[a][x],stmin[b-(1<<x)+1][x]);
        cout<<ans<<endl;
    }
    return 0;
}
相关推荐
爱吃生蚝的于勒6 分钟前
深入学习指针(5)!!!!!!!!!!!!!!!
c语言·开发语言·数据结构·学习·计算机网络·算法
羊小猪~~10 分钟前
数据结构C语言描述2(图文结合)--有头单链表,无头单链表(两种方法),链表反转、有序链表构建、排序等操作,考研可看
c语言·数据结构·c++·考研·算法·链表·visual studio
王哈哈^_^35 分钟前
【数据集】【YOLO】【VOC】目标检测数据集,查找数据集,yolo目标检测算法详细实战训练步骤!
人工智能·深度学习·算法·yolo·目标检测·计算机视觉·pyqt
星沁城37 分钟前
240. 搜索二维矩阵 II
java·线性代数·算法·leetcode·矩阵
脉牛杂德1 小时前
多项式加法——C语言
数据结构·c++·算法
legend_jz1 小时前
STL--哈希
c++·算法·哈希算法
kingmax542120081 小时前
初三数学,最优解问题
算法
一直学习永不止步1 小时前
LeetCode题练习与总结:赎金信--383
java·数据结构·算法·leetcode·字符串·哈希表·计数
小刘|2 小时前
《Java 实现希尔排序:原理剖析与代码详解》
java·算法·排序算法
jjyangyou2 小时前
物联网核心安全系列——物联网安全需求
物联网·算法·安全·嵌入式·产品经理·硬件·产品设计