基礎資料結構
22703 王培軒
講師介紹
- 22703
- 沒什麼特色
基礎中的基礎
前綴和
假設有陣列\(a\),定義前綴和(prefix sum)陣列\(b\)
\(b_i=\sum_{k=1}^{i}a_k\)
舉例
\(a\):1 2 3 4 5
prefix sum:1 3 6 10 15
可以幹嘛
\(O(n)\)預處理
\(O(1)\)求任意\([l,r]\)區間和
差分
假設有陣列\(a\),定義差分(differences)陣列
\(d_i=a_i-a_{i-1}\),且\(d_0=a_0\)
即可得\(a_i=\sum_{k=1}^{i}d_i\)
前綴的逆運算為差分
舉例
\(a\):1 3 6 10 15
differences:1 2 3 4 5
可以幹嘛
暫時沒有想到裸的運用><
但前綴跟差分到處都可以派上用場
待丟題
基礎線段樹
(Segment Tree)
俗話說...
任何區間題目都有一個中國人能想到線段樹的做法
我們想要解決
有長度\(n\)的陣列\(a\),\(q\)筆詢問,每次
1.詢問\([l,r]\)之區間和
2.將\(a_i\)改為\(x\)
\(n\leq 10^5,q\leq 10^5\)
暴力做太慢,用前綴和要修改也太慢...
線段樹來了
- 完全二元樹
- 每個節點儲存一個區間的資料
- 兩個子樹儲存當前區間左右兩邊的資料
- 共\(O(\log n)\)層
修改
最多修改\(O(\log n)\)個節點
Title Text
- Bullet One
- Bullet Two
- Bullet Three
查詢
最多查詢\(O(\log n)\)個節點
寫法
- 陣列型(基本款)
- 指標型(一些比較複雜的東西會用到)
- 偽指標型(指標型的常數改良(?)版)
陣列型
若當前節點存在\(seg[cur]\),則他的左子節點存在\(seg[cur*2]\),右子節存在\(seg[cur*2+1]\),從\(1\)開始
通常開\(seg[4*MAXN]\)
查詢、修改時遞迴處理
最好寫也最簡潔的一種
陣列型
int seg[MAXN*4];
void modify(int l,int r,int cur,int ind,int val){
if(r-l<=1){
seg[cur]=val;
return;
}
int mid=(l+r)/2;
if(ind<mid) modify(l,mid,cur*2,ind,val);
else modify(mid,r,cur*2+1,ind,val);
seg[cur]=seg[cur*2]+seg[cur*2+1];
}
int query(int l,int r,int cur,int ql,int qr){
if(l>=qr||r<=ql) return 0;
if(ql<=l&&qr>=r) return seg[cur];
int mid=(l+r)/2;
return query(l,mid,cur*2,ql,qr)+query(mid,r,cur*2+1,ql,qr);
}
它還可以維護...
- 最大/最小值
- XOR
- 各種
總結
線段樹是一種將區間分塊的思想,這只是最基礎的一種應用,還有各式各樣的線段樹在等著各位。
之後資讀應該還有機會講。
BIT
What
BIT(Binary Indexed Tree),又稱Fenwick tree
這可以幹嘛
可以算是線段樹的瘦身版,\(O(\log n)\)維護前綴和
區間合則需兩個前綴和相減
基礎資料結構
By peter940324
基礎資料結構
- 183