高階數據結構---ST表

hello大家好,今天是2025年8月23日,我要來給大家分享的是一個高階數據結構---ST表。

一:引入

1.RMQ問題:

對于一個長度為 n 的序列,有 m 次查詢操作,每次查詢為一個區間 [l,r] 的最大值(最小值)。

上述問題可以用線段樹來解決。但是殺雞焉用宰牛刀,對于這種靜態問題,我們可以使用代碼量更少的方式來解決------ST表

2.ST表:

ST表(Sparse Table,稀疏表)是一種基于動態規劃和倍增思想實現的數據結構形式上是一張二維表格ST表通過預處理一些信息,從而快速處理區間查詢。(類似前綴和數組~)其中,預處理的時間復雜度為 O(n * log n),查詢操作為 O(1)由于在查詢前需要預處理出一些信息,因此ST表基本上只能解決靜態問題。

ST表

將信息預處理完畢之后,對于查詢操作只需要在這張二維表格中拿值就可以了。

這里解釋一個名詞:靜態問題---以數組操作為例:

有靜態問題就會有動態問題,靜態問題就是只有查詢操作沒有修改操作,或者查詢操作是在所有修改操作全部結束之后進行。相比之下,動態問題就是修改操作和查詢操作交叉進行。

ST表能夠解決的問題(靜態問題)線段樹絕大多數都可以解決,線段樹能解決的問題(靜態問題 & 動態問題)ST表就不一定可以解決。

3.ST表維護的信息:

ST表維護的信息需要滿足結合律和可重復貢獻。(例如區間最值以及區間gcd

這里借助一張圖解釋一下什么是結合律和可重復貢獻。

如果不滿足結合率和可重復貢獻,ST表就不能解決。例如區間和以及區間乘積。

二:ST表的實現

計算機中的 log 默認是下取整的,在這里提前說一下,下面就不過多贅述了。

1.ST表維護信息的方式:

對于一個長度為 n 的序列,有 m 次查詢操作,每次查詢為一個區間 [l,r] 的最大值。

由于區間最值不滿足可差性,因此不能像前綴和數組一樣搞一張一維表格來預處理某些區間的信息。由于二維表格可以直接用來表示區間,那么可以嘗試用二維的表格來預處理,一種直接的方式就是:f[i][j] 表示區間 [i, j] 的最值。

這種方式肯定是可以解決問題的。但是,RMQ 問題的數組一般都是 1e5~1e6 級別的長度,這張二維表格根本無法創建出來(空間溢出)。

我們嘗試使用倍增的思想?2^{j} = 2^{j - 1} + 2 ^ {j - 1}?優化一下狀態表示:

f[i][j] 表示:從 i 位置開始,長度為?2^j?的區間中,所有元素的最值。

以數組 a = 【5,2,4,6,1,7,5,0,9,3】為例,我們會用下述方式維護區間最大值信息。

這就是稀疏表的由來,并不是把所有的區間信息存下來,只存長度為 2^j 的區間信息。

優化之后,第二維空間大小 n 只需保證 2^n >= N 就行。25~30就足夠了。可見,這個優化是非常有效的。

2.ST表的查詢

預處理工作結束之后,我們能否使用預處理出的信息快速查詢區間最值呢?

比如,我們要查詢區間【l,r】的最大值:

根據狀態表示,我們只需要先求出 k = log(2)(r - l + 1)(下取整),然后再從 f[l][k] 和

f[r - (1 << k) + 1][k] 兩個格子中取最大值即可。

3.記憶區間起點和區間終點的技巧

  • 起點 + 區間長度 = 下一個區間的起點。
  • 終點?-? 區間長度 = 上一個區間的終點。

4.ST表的實現

初始化

#include <iostream>
#include <cmath>using namespace std;
const int N = 1e5 + 10;int n;
int a[N], f[N][25]; // j ^ 25 >= N 就行  void init()
{for(int i = 1; i <= n; i++) f[i][0] = a[i];for(int j = 1; j <= log2(n); j++)for(int i = 1; i + (1 << j) - 1 <= n; i++)f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}

查詢

int query(int l, int r)
{int k = log2(r - l + 1);return max(f[l][k], f[r - (1 << k) + 1][k]);
}

5.優化log(看題目情況)

如果查詢次數過多,是會有一個 log 的開銷的。如果把 log1~logn 全部預處理出來,那么查詢操作的 k 就可以在 O(1)的時間得到。

對于對數運算,有如下公式:

因此可以通過遞推,預處理出來所有的 log1 ~ logn。

加了優化的ST表:

#include <iostream>
#include <cmath>using namespace std;
const int N = 1e5 + 10;int n;
int a[N], f[N][25]; // j ^ 25 >= N 就行  
int lg[N];void init()
{lg[0] = -1; // 為了方便遞推 lg[1] = lg[0] + 1 == 0 for(int i = 1; i <= n; i++){lg[i] = lg[i >> 1] + 1;f[i][0] = a[i];} for(int j = 1; j <= lg[n]; j++)for(int i = 1; i + (1 << j) - 1 <= n; i++)f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}int query(int l, int r)
{int k = lg[r - l + 1];return max(f[l][k], f[r - (1 << k) + 1][k]);
}

三:ST表模板題

題目一:【模板】ST表 && RMQ 問題

題目鏈接:【模板】ST表 && RMQ 問題

#include <iostream>
#include <cmath>using namespace std;const int N = 1e5 + 10;int n, m;
int f[N][25];int RMQ(int l, int r)
{int k = log2(r - l + 1);return max(f[l][k], f[r - (1 << k) + 1][k]);
}int main()
{scanf("%d%d", &n, &m);for (int i = 1; i <= n; i++) scanf("%d", &f[i][0]);//初始化for (int j = 1; j <= log2(n); j++){for (int i = 1; i + (1 << j) - 1 <= n; i++){f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);}}while (m--){int l, r; scanf("%d%d", &l, &r);printf("%d\n", RMQ(l, r));}return 0;
}

題目二:gcd 區間

題目鏈接:gcd 區間

#include <iostream>
#include <cmath>using namespace std;const int N = 1e3 + 10;int n, m;
int f[N][25];int gcd(int a, int b)
{return b == 0 ? a : gcd(b, a % b);
}int query(int l, int r)
{int k = log2(r - l + 1);return gcd(f[l][k], f[r - (1 << k) + 1][k]);
}int main()
{cin >> n >> m;for (int i = 1; i <= n; i++) cin >> f[i][0];for (int j = 1; j <= log2(n); j++){for (int i = 1; i + (1 << j) - 1 <= n; i++){f[i][j] = gcd(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);}}while (m--){int l, r; cin >> l >> r;cout << query(l, r) << endl;}return 0;
} 

四:ST表練習題

題目一:質量檢測

題目鏈接:質量檢測

這道題目的最優解是單調隊列 O(n),但是我們這個專題是 ST 表,因此給出ST表的解法,下去之后也要嘗試一下使用單調隊列解決這道問題。

#include <iostream>
#include <cmath>
#include <cstring>using namespace std;const int N = 1e5 + 10;int n, m;
int f[N][25];int query(int l, int r)
{int k = log2(r - l + 1);return min(f[l][k], f[r - (1 << k) + 1][k]);
}int main()
{memset(f, 0x3f, sizeof f);cin >> n >> m;for (int i = 1; i <= n; i++) cin >> f[i][0];for (int j = 1; j <= log2(n); j++){for (int i = 1; i + (1 << j) - 1 <= n; i++){f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);}}for (int i = 1; i + m - 1 <= n; i++){cout << query(i, i + m - 1) << endl;}return 0;
} 

題目二:Balanced Lineup G

題目鏈接:Balanced Lineup G

#include <iostream>
#include <cstring>
#include <cmath>using namespace std;const int N = 5e4 + 10;int n, m;
int f[N][28];
int g[N][28];int query(int l, int r)
{int k = log2(r - l + 1);return max(f[l][k], f[r - (1 << k) + 1][k])- min(g[l][k], g[r - (1 << k) + 1][k]);
}int main()
{cin >> n >> m;memset(g, 0x3f, sizeof g);for (int i = 1; i <= n; i++){cin >> f[i][0];g[i][0] = f[i][0];}for (int j = 1; j <= log2(n); j++){for (int i = 1; i + (1 << j) - 1 <= n; i++){f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);g[i][j] = min(g[i][j - 1], g[i + (1 << (j - 1))][j - 1]);}}while (m--){int l, r; cin >> l >> r;cout << query(l, r) << endl;}return 0;
}

今天的分享就到這里了~~,如果大家有疑問的話,歡迎下來之后和我溝通~~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/920192.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/920192.shtml
英文地址,請注明出處:http://en.pswp.cn/news/920192.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

docker 安裝nacos(vL2.5.0)

查找nacos 的所需的鏡像版本 https://hub.docker.com/r/nacos/nacos-server/tags 拉取你所需的版本&#xff08;我們用v2.5.0&#xff09; docker pull nacos/nacos-server:v2.5.0 注意&#xff1a;因為我們需要掛載外配置文件 直接用volume 掛載目錄 缺少初始文件報錯 我們…

在github上通過dmca數字版權申訴侵權并刪除侵權倉庫

DMCA是什么&#xff1f; 《數字千年版權法案》&#xff08;DMCA&#xff09;為版權所有者&#xff08;包括軟件開發人員&#xff09;創建了一個標準化的流程&#xff0c;要求GitHub刪除侵權內容。您可以在美國版權局的官方網站上找到有關DMCA的更多信息。有關GitHub如何處理DM…

AI安全監控與人才需求的時間悖論(對AI安全模型、AI安全人才需求的一些思考)

當監控者與被監控者都是AI時&#xff0c;誰來監控監控者&#xff1f;這個看似簡單的問題&#xff0c;卻揭示了人工智能安全領域的根本性困境。一、問題的提出&#xff1a;當AI監控AI 隨著大語言模型和生成式AI的快速發展&#xff0c;AI系統在元認知層面的能力越來越強&#xff…

AI模型部署 - 大型語言模型(LLM)推理部署中的實際顯存評估

目錄 第一部分:大型語言模型(LLM)推理顯存占用的核心原理 1.1 顯存占用的主要構成部分 1.2 影響顯存占用的關鍵因素 1.2.1 模型架構:MoE vs. 稠密模型 1.2.2 上下文長度與并發數 1.2.3 部署方式與推理框架 1.2.4 硬件能力 第二部分:顯存占用的精確計算方法 2.1 模…

【大語言模型 16】Transformer三種架構深度對比:選擇最適合你的模型架構

【大語言模型 16】Transformer三種架構深度對比&#xff1a;選擇最適合你的模型架構 關鍵詞&#xff1a;Transformer架構&#xff0c;Encoder-Only&#xff0c;Decoder-Only&#xff0c;Encoder-Decoder&#xff0c;BERT&#xff0c;GPT&#xff0c;T5&#xff0c;模型選擇&…

【LeetCode 熱題 100】31. 下一個排列

Problem: 31. 下一個排列 文章目錄整體思路完整代碼時空復雜度時間復雜度&#xff1a;O(N)空間復雜度&#xff1a;O(1)整體思路 這段代碼旨在解決經典的 “下一個排列” (Next Permutation) 問題。問題要求重新排列一個整數數組&#xff0c;使其變為字典序上的下一個更大的排列…

【Linux 進程】進程程序替換

文章目錄1.進程替換的六個庫函數2.execl1.進程替換的六個庫函數 使用 man 3 execl 進行查詢&#xff0c;3表示 Linux 中的3號手冊&#xff0c;即為庫函數&#xff08;例如C標準庫中的庫函數&#xff0c;printf&#xff0c;malloc&#xff09; man 1: 用戶命令&#xff08;在sh…

ReasonRank: Empowering Passage Ranking with Strong Reasoning Ability

主要內容總結 本文提出了一種具有強推理能力的列表式段落重排序模型ReasonRank,旨在解決現有重排序模型在推理密集型場景(如復雜問答、數學問題、代碼查詢等)中表現不佳的問題,核心原因是這類場景缺乏高質量的推理密集型訓練數據。 為解決這一問題,研究團隊: 設計了自動…

不卡頓、不掉線!穩定可靠的體育賽事直播系統源碼解析

在體育和電競行業&#xff0c;實時直播系統已經成為平臺的標配。無論是 OTT、比分直播網站&#xff0c;還是綜合類體育社區&#xff0c;用戶對直播體驗的要求越來越高&#xff1a;不卡頓、不掉線、實時性強。那么&#xff0c;從技術角度出發&#xff0c;一個穩定可靠的 體育賽事…

三菱FX5U PLC訪問字變量的某一位

三菱FX5U PLC氣缸控制功能塊 三菱FX5U氣缸控制功能塊(完整ST源代碼+示例程序)_三菱fx5u標簽氣缸報警程序功能塊-CSDN博客文章瀏覽閱讀560次,點贊5次,收藏2次。如果機器包含100個氣缸,我們只需要修改數組的元素數量就可以了,效率非常的高。待續....博途PLC 面向對象系列之“…

Java大廠面試全真模擬:從Spring Boot到微服務架構實戰

Java大廠面試全真模擬&#xff1a;從Spring Boot到微服務架構實戰 面試場景&#xff1a;某互聯網大廠Java后端崗位&#xff0c;候選人謝飛機&#xff08;水貨程序員&#xff09; 第一輪&#xff1a;基礎與框架認知 面試官&#xff1a;你好&#xff0c;謝飛機&#xff0c;先簡單…

Unity游戲打包——Mac基本環境雜記

1、安裝 Homebrew若未安裝&#xff0c;在使用 brew 命令時將提示 zsh: command not found: brew安裝命令&#xff1a;/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"2、更換終端默認 Shell 為 zsh查看已安裝的shell&#…

服務組件體系結構(SCA)全景解析

服務組件體系結構&#xff08;SCA&#xff09;全景解析SCA&#xff08;Service Component Architecture&#xff09;是 SOA 生態中專門用來“把服務拼起來并跑起來”的規范。它通過語言中立、協議可插拔、裝配聲明式三大能力&#xff0c;把“接口—實現—協議”徹底解耦&#x…

問:單證碩士含金量是否不足?

很多人認為花幾萬塊錢讀一個同等學歷申碩&#xff0c;含金量并沒有那么高&#xff0c;但事實卻并非如此。今天我們從證書和學習的兩個方面來聊一下同等學歷申碩的含金量到底是如何的。一、單證含金量看以下幾點&#xff1a;&#xff08;1&#xff09;國家認證與學信網可查 …

0.04% vs 0.1%:精度差一點,逆變器性能差距有多大?

一臺光伏逆變器損失的功率可能僅僅源于0.3%的MPPT效率差距。這個足以影響產品競爭力的數字&#xff0c;可能并非算法優劣&#xff0c;而在于測試源頭的精度選擇&#xff1a;是0.04%還是0.1%&#xff1f;本文通過四大測試場景的量化對比&#xff0c;揭示不同的測試精度如何影響產…

Docker Hub 鏡像一鍵同步至阿里云 ACR

&#x1f433; Docker Hub 鏡像一鍵同步至阿里云 ACR 本腳本用于 從 Docker Hub 拉取鏡像并推送到阿里云容器鏡像服務&#xff08;ACR&#xff09;。 它通過 Python 的 docker SDK 封裝了完整流程&#xff1a;拉取 → 重命名 → 登錄 → 推送&#xff0c;并在控制臺實時輸出進度…

軟考-系統架構設計師 計算機系統基礎知識詳細講解

個人博客&#xff1a;blogs.wurp.top 一、計算機系統組成與多級層次結構 1. 馮諾依曼體系結構 (核心考點) 這是所有現代計算機的理論基礎。核心思想是 “存儲程序” 。 五大部件&#xff1a;運算器、控制器、存儲器、輸入設備、輸出設備。工作流程&#xff1a;指令驅動。CP…

DLL文件丟失怎么辦?這個修復工具一鍵搞定!

軟件介紹&#xff08;文末獲取&#xff09;是不是經常遇到這種情況&#xff1a;安裝軟件時提示缺少DLL文件&#xff1f;打開游戲時出現DLL錯誤&#xff1f;或者運行程序時突然崩潰&#xff1f;今天給大家推薦一款超好用的DLL修復工具——4DDiG DLL Fixer&#xff0c;一鍵解決所…

并發容器小結及ConcurrentSkipListMap介紹——并發系列(十一)

目錄 概述 ConcurrentHashMap CopyOnWriteArrayList ConcurrentLinkedQueue BlockingQueue ConcurrentSkipListMap 設計目的 功能特性 與其他相關類對比 適用場景 概述 JDK提供的這些容器大部分在 java.util.concurrent 包中。我們這里挑選出了一些比較有代表性的并發…

藍思科技半年凈利超11億,藍思成績單怎么分析?

8月26日&#xff0c;藍思科技發布2025年半年度業績報告&#xff0c;其中&#xff0c;凈利潤11.43億元&#xff0c;同比增長32.68%。這份成績單我們該怎么分析&#xff1a;首先&#xff0c;藍思科技營收與利潤雙增長&#xff0c;成長能力持續凸顯。報告期內&#xff0c;公司營業…