鄭州集訓DAY3筆記

2021-08-09 01:42:57 字數 3933 閱讀 4109

成績:

題目成績

評價t1

100感動。。總算上了一百分

t210

本來以為能騙到40???t30

真的不會做

字串hash:一種從字串到整數的對映

通過這樣的對映,把比較兩字串是否相同轉化為兩整數是否相同

若比較發現兩字串hash值相等,我們認為兩字串很大可能是相同的

另一方面,若 hash 值不等,則兩字串一定不同

比較字串 o(l),比較整數 o(1)

競賽中常用的 hash 策略

把字串視為乙個 base 進製的大整數,對某個質數 p 取模得到 hash 值

sum_i = (sum_ *base + str_i) mod p

base 可以取 31、131、13131 等,需要滿足 base > |字符集|

p 取 long long 範圍內乙個質數,注意溢位問題

使用 unsigned long long 自然溢位可以視為對 2^64 取模

但是可能被卡(對任意base)

害怕 hash 被卡的同學,也可以選擇雙 hash(常數翻倍

常用技巧

—-給定字串 s,預處理出它的字首 hash 函式;同時計算好 mod p 意義下 base 的冪次表

sum[i] = (sum[i - 1] * base + str[i]) % p

pw[i] = (pw[i - 1] * base) % p

基礎應用:

提取一段子串的 hash 值

合併兩個串的 hash 值

o(\log n) 計算兩個子串的 lcp 和字典序大小

又稱字母樹,可以用來維護字串集合

優化思想是,利用字串的公共字首來減少查詢時間,最大限度地減少無意義的比較

這是一顆trie樹。有根樹,每條邊上存有乙個字元,從根到每個葉子的路徑上經過的字元寫下來,對應了乙個字串。

支援的操作有:插入、查詢、刪除。

可以參考:並查集入門by柴犬首相

原理

對每個集合,建立乙個有根樹的結構,令樹的根為整個集合的「代表」,想知道兩個元素是否在同一集合,只需比較它們的代表,合併時,將一棵樹接到另一棵下邊即可。

優化策略

應用

最小生成樹的 kruskal 演算法

tarjan離線lca演算法。

帶權並查集

在一些應用中,可以在每個點上額外維護一些資訊,表示「它與父親」之間的關係,進而嘗試推算集合中任意兩個元素之間的關係。

例題——食物鏈

題目位址luogu食物鏈

只按秩合併

只按秩合併的並查集,可以在合併的時候一定程度上保留元素合併在一起的 「過程」

支援這樣幾種操作的資料結構:

插入乙個優先順序為 key 的元素

詢問優先順序最高的元素

刪除優先順序最高的 / 任意乙個元素

公升高乙個元素的優先順序值

優先佇列一般使用堆來實現

最經典的堆即為大名鼎鼎的二叉堆

二叉堆是乙個完全二叉樹結構,並且它具有堆性質:,每個點的優先順序高於它的兩個孩子(如果有)。可以用乙個數字來儲存二叉堆,避免指標:

1 是根結點,對於 x,它的左右孩子分別是 2x 和 2x+1,容易驗證 n 個點的二叉堆,它用到的陣列即為 1 ~ n,給定乙個大小為 n 的陣列,我們可以 o(n) 的建堆。

調整

隨著操作的進行,二叉堆的「堆性質」可能會遭到破壞,為此我們定義兩種調整操作,來維護二叉堆的堆性質保持不變

向上調整:

當乙個點的優先順序公升高時,我們需要向上調整

比較它和它的父親的優先順序,它的優先順序高就與父親交換位置並遞迴進行

向下調整:

當乙個點的優先順序降低時,我們需要向下調整

比較它和它左右兒子中優先順序較高的那個,它的優先順序低就與兒子交換並遞迴下去

容易驗證兩種操作的複雜度均為 o(\log n)

操作

插入:插入乙個葉子,然後向上調整

詢問:返回 a[1]

刪除根:令 a[1] = a[n],然後向下調整

左偏樹

也是一種優秀的堆,並且是支援合併的(可並堆),比較簡單,容易實現。但是我們不講。

應用

- dijkstra 演算法和 prim 演算法的優化

- 哈夫曼編碼

- 一些奇怪的應用

可以參考:線段樹入門by柴犬首相

線段樹是一種二叉搜尋樹,一般可以用來維護序列的子區間

結構

對乙個長度為 n 的序列建線段樹,根結點即表示 [1, n]

對於乙個表示 [l, r] 的節點:,若 l = r,則它是葉子。否則,令 m = (l + r) / 2,它有左右兩個孩子,分別記為:[l, m] 和 [m + 1, r],不難驗證,這樣乙個線段樹中有 2n - 1 個節點,並且樹的深度是 o(\log n) 級別。

原理

線段樹的優化思想:

根據問題的要求,用每個節點維護它對應的子區間中、可以高效合併的相關資訊,在動態的序列問題中,對於修改操作沒有動過的部分。我們可以考慮把這些地方的求解的結果儲存並復用,從而達到優化程式效率、降低複雜度的目的。

一種支援單點修改和查詢字首和的資料結構,複雜度為 o(\log n),但是常數很小。

原理

定義 lowbit(x),表示將 x 寫成二進位制後,只保留二進位制下最低乙個 1 對應的整數

例:lowbit(1001100) = 100, lowbit(1000) = 1000

十進位制:lowbit(76)=4, lowbit(8) = 8

對乙個陣列 a,我們構造陣列 c,其中

c[i] = sum (. a[i - lowbit(i) + 1 … i] )

巧妙的事情來了:

我們查詢 a 的字首和只需要訪問 c 中 log n 個節點

修改 a 中任意乙個元素的值,只需要同時修改 c 中的 log n 個節點

於是可以在 o(\log n) 的時間內支援單點修改、字首和查詢

複雜度均為 o(\log n)

優點

樹狀陣列常數小、跑得快;線段樹常數較大,跑得稍慢

樹狀陣列相比線段樹好實現

樹狀陣列可以比較簡單地推廣到二維

不足

樹狀陣列的功能是線段樹的子集

對二維陣列 a,維護 c 表示

c[i][j] = sum( a [ i-lowbit(i)+1 … i] [ j-lowbit(j)+1 … j] )

可以支援二維陣列的單點修改、查詢字首矩形的和

複雜度 o(\log^2 n)

想支援對陣列 a 的區間加整數、區間查詢和,考慮 a 的差分陣列 b[i] = a[i] - a[i - 1],區間加對 b 只修改兩個位置!同時,為了支援查詢 a 的字首和,經過一番推導,發現只需維護 b[i] 和 i * b[i] 的字首和即可,複雜度 o(\log n)

今天講了資料結構,但是呂欣大佬晚上趕車回家過中秋節,。。我們樹狀陣列實在是沒有怎麼講,要再看。

北京集訓DAY3

消去合法的序列 剩下的不合法序列一定是 3兩種括號個數各加1除2 手算一下即可4 5 include 6 include 7 include 8 9const int maxn 100010 10 11int len,top,cnt 1213 char s maxn 1415 inthh 25int...

長沙集訓day3(總結)(爆零記)

昨天晚上打了打codeforce,睡的比較晚,早上七點三十才起0.0 沒有找到今天題的ppt,就先不弄了。t1 題目大概就是乙個有許多腳的東西,每個腳都有他的初始位置和他的速度,每一次後面的腳超過前面的腳都會發生一次碰撞,讓你求出都有那個腳超過那個腳了。然後發生超越和被超越的腳組成兩個集合a,b。然...

省隊集訓DAY3

一共要使用六根木棍,那麼分割的方法就兩種,那麼關鍵就是要計算2,3的數量。cnt1 i 表示每種長度的木棍的方案數 cnt2 i 最初表示用不同的木棍拼成長度為i邊的方案數,後來表示選出四根木棍構成的方案數。cnt22 i 表示用兩個長度相同的不同木棍拼成長度為i的邊的方案數。cnt3 i 表示用三...