ST表 從入門到入門 淺顯理解

2022-07-26 02:51:10 字數 3254 閱讀 6879

st 表是個好東西,雖然前些天 ldq 學長已經講完啦,但是那天他講了那麼多,讓智商受限的我完全沒有全部接受,選擇性的扔掉了一部分(其實不捨的扔,記不住qaq)。

st 表最簡單的應用就是查詢區間最大值(或著最小值,這裡以最大值為例),它(單純 st 表自己)需要你先修改之後(如果有修改要求),得到乙個確切陣列之後,經過o ( nlogn )的預處理,然後就可以做到o ( 1 )查詢啦。

st 表的預處理操作:

對於乙個有 n 個數的 a [ n ] ,如果需要用乙個二維陣列 f [ n ] [ t ] ,其中 n 是指的用這 n 個數,t 是指的 n 最大是 2 的多少次冪,即 2 ^ t >= n 向上取整。

陣列 f [ n ] [ t ] 是用來幹什麼的呢?f [ i ] [ j ] 是指以 a [ n ] 中第 i 個數開始,長度為 2 ^ j 的最大值,這樣就清楚了陣列 f [ n ] [ t ] 中 t 的**啦吧。

所以我們要做的第一步預處理中:

f [ i ] [ 0 ] 就是存的 a [ i ] 值自己。

f [ i ] [ 1 ] 就是存的從 a [ i ] 開始往後乙個,即 a [ i ] 和 a [ i + 1 ] 的最大值

以此類推,就可以得到我們想要的陣列 f [ n ] [ t ] 啦。

那麼我們怎麼去實現這個東西呢?不能乙個個的去列舉吧,那樣的話,還不如用線段樹(我是這麼想得h_h),當然啦,這個問題在 st 表被想出來的時候就解決啦,那就是遞推得到,先看一下**(不理解沒關係,慢慢看)。

int f[maxn][20];

int a[maxn];

int n;

void st()

}}

第乙個 for 迴圈 應該沒什麼理解障礙,就是上面說的把自己存進去,因為是 2 ^ 0 。

第二個是兩個 for 迴圈,也就是遞推的部分,我們這樣子來實現:

f [ i ] [ j ] 代表以 a [ i ] 開始長度為 2 ^ j 的數裡面的最大值,即 f [ i ] [ j ] = max ( a[ i ] , …… , a [ i + 2 ^ j ] )。

我們先看乙個簡單的例子:現在乙個數列是 a [ ]  = , 那麼 (下標)0 ~ 2的最大值 max1 ,和 3 ~ 4 最大值 max2,兩個裡面的最大值 max 就是整個區間的最大值,這個很好理解吧!

那麼我們回到求 f [ i ] [ j ] 上,這個問題就變的和這個一樣子啦,不過就是需要改變一下長度,我們把這個長度 len = 2 ^ j 的區間分成長度分別為 len1 = 2 ^ ( j - 1 ) 和 len2 =  2 ^ ( j - 1 ) 的這兩個區間,只要求出來這兩個的最大值就可以像上面那樣子得到最終結果啦。

所以我們就可以理解上面我說的意思啦:f [ i ] [ j - 1] 代表從 a [ i ] 開始前 2 ^ ( j - 1 ) 個元素的最值,f [ i + ( 1 << ( j - 1 ) )] [ j - 1 ] 就是後面這 2 ^ ( j - 1 ) 個元素裡面的最值,這樣子合併取個最大值,就是總的最大啦,也就是**中的:f [ i ] [ j ] = max ( f [ i ] [ j - 1 ] , f [ i + ( 1 << ( j - 1 ) ) ] [ j - 1 ] ) 。

這裡有幾點需要注意的(自己xj說的,不對可以告訴我哈):

第一點是大家都知道的,在預處理中控制第二維的迴圈,也就是for ( int j = 1; j <= t; j ++),一般的話 t 取 20 左右就可以啦,你要是不放心就先計算一下再開陣列一樣的,這個一定要放在外面,因為我們要通過遞推得到,如果放在裡面的話,就得不到我們想要的結果啦(可以感覺一下子)。

第二點就是那個 f [ i ] [ j ] 這裡可能有理解誤區,就算是不夠 2 的整數次冪也沒有關係的,初始化或者邊界處理一下就可以啦,最大值最小值對應上相應的初始化。

第三點是對於 1  << ( j  - 1 )  這個東西,這和求那個 t 的時候的意思乙個樣子啦,這樣子寫比較高大尚一些。

st 表在預處理時採用倍增和dp思想。

st 表查詢操作:

關於查詢操作,想一想怎麼樣子可以做到o ( 1 )查詢的呢。

先來看簡單的栗子(簡單的看懂啦,難得就可以啦):

a [ ]  = ,在這些數裡面我們想知道 1 ~ 8(下標從 0 開始) 的最大值。

如果我們已經用陣列 f [ n ] [ t ] 存好啦,我們可以先計算一下長度可以是 2 的多少次冪,左端點是 x = 1, 右端點是 y = 8,長度 m = log ( y - x  + 1) / log ( 2 ),我們需要差的就是從 a [ x ] 開始 m 這麼長的區間,由於 m 存在邊界問題,所以我們還需要查的區間就變成 [ x ] [ m ] ,但是這樣子查的話不免可能會漏掉東西而且預處理的結果我們也沒有用到,所以我們把這個 m 的長的區間分成啦兩個部分,也就可以利用預處理的結果啦。

所以區間就變成了 [ x ] [ x + 2 ^ m - 1 ] 和 [ y - 2 ^ m + 1] [ y ] ,這兩個區間分別對應的陣列 f [ n ] [ t ] 是 f [ x ] [ m ] 和 f [ y - ( 1 << m ) + 1 ] [ m ] (這個可能存在不是很好理解的問題,不過不要忘記啦 f [ i ] [ j ] 的意思,是指從 a [ i ] 開始的長度為 2 ^ j 的最值,這樣就可以啦,實在不好理解,可以手動畫一畫)。

**:

int query(int x, int y)

完整的**(其實僅僅是一點點,可以戳我):

const int maxn = 1000004;

int f[maxn][20];

int a[maxn];

int n;

void st()

}}int query(int x, int y)

---------------------

就羅嗦這麼多啦,還有好多作業qaq(看在我這麼慘的份上,要是**,別忘記啦我的位址qwq)

Redis從入門到入門

2安裝1.1支援的儲存結構 remote dictionary server 以字典儲存資料,允許其他應用通過tcp協議訪問字典內容。支援的鍵值型別 優點 redis的字典儲存方式和多重鍵值儲存方式,使得程式設計師可以直接將程式中的資料對映到redis中,資料在redis中的儲存方式和其在程式中的儲...

入門者筆記 ST表

原題位址 題目描述 為了檢測生產流水線上總共n件產品的質量,我們首先給每一件產品打乙個分數a表示其品質,然後統計前m件產品中質量最差的產品的分值q m min,以及第2至第m 1件的q m 1 q m 2 最後統計第n m 1至第n件的q n 根據q再做進一步評估。請你盡快求出q序列。輸入輸出格式 ...

TestNg 從入門到深入理解

執行順序 從上往下 引數 include 要執行的方法 exclude 除了這裡的方法其他的都要執行 test prioority 整數值 值越小,優先順序越高,預設是0 用例的併發執行 test級的併發 class級的併發 test threadpoolsize 5,invocationcount...