大部略
棧 , 但是push的時候要彈出所有比他小/大的(多用於優化dp)
佇列 , 同單調棧
核心:lowbit(x) = (x) & (-x)
...其實lowbit(x) = 2^x的最低非0位
pion8012初賽中考了...但只涉及正數...
考慮x>0時-x等於多少:-x在二進位制中的意義為x所有位取反後+1 , 那麼他的第乙個非0位以前的都是0 , &後結果為0 , 在第乙個非0位時-x發生進製使哪位為1 , 那麼這位為1 , 再以後呢?為0 , 所以&也為0
\(c_ = \sum_^ c_\)
我們為什麼要設計前面的\(c_\)為這個奇怪的數?
答案揭曉!為了查詢!當查詢時我們只需要遍歷查詢數的每個lowbit , 將值加上\(c_\)
查詢時間複雜度為\(o(logn)\)
那麼這為什麼對呢?因為:
畫出這顆樹發現的確是對的qaq其實是我不會證
關於**:
void modify(int x , int y)/*modify a[x] to a[x]+y*/
int query(int x)/*query a[1]+...+a[x]*/
其實一開始你覺得比較難 , 但其實很基礎
線段樹每次將區間分成兩個小區間 , 到底層遞迴 ;
用指標寫偽**就是
query()
int sum = 0 ;
if(!this->ls) sum+=this->ls.query()
if(!this->rs)sum+=this->rs.query()
return sum ;
//什麼?你問我為什麼要寫指標?**短!
但是你**肯定不能這麼寫...線段樹維護的不只和 , 需要zici區間查詢 :
關於區間查詢
query(i,j,ni,nj,p)
if(i<=ni && j<=nj) return value[p] ;
int m = (s + t) >> 2, sum = 0;
if (l <= m) sum += query(l, r, s, m, p * 2);
if (r > m) sum += query(l, r, m + 1, t, p * 2 + 1);
return sum;
pushdown
pushdown(p,m,s,t)
d[p * 2] += b[p] * (m - s + 1), d[p * 2 + 1] += b[p] * (t - m),b[p * 2] += b[p], b[p * 2 + 1] += b[p];
區間修改:
每次執行單點修改並給節點打上lazytag , 需要時下放
板子#include#include#define ll long long
#define maxn 100000
int p , arr[maxn+5];
using namespace std ;
struct nodetr[4*maxn+5];
void build(int root,int l,int r)
tr[root].v%=p ;
}void pushdown(int root,int l,int r)
void u_m(int root,int il,int ir,int l,int r,ll k){
if(r見可持久化資料結構
資料結構小結
資料結構就是乙個集合 資料結構 邏輯結構 線性資料結構 線性表 棧 佇列 字串 陣列 對應順序表 非線性資料結構 集合 樹結構 圖 儲存結構 順序儲存結構 順序表 非順序儲存結構 鏈式儲存結構 鍊錶 由指標來實現 雜湊 雜湊 索引 一種邏輯結構可以使用不同的儲存結構,那麼就會形成不同的名稱。線性表是...
資料結構小結
if you give a person a program,you ll frustrate him for a day.if you teach a person to program,you will frustrate them for a lifetime 1946年世界上第一台計算機問世...
資料結構小結
有四種基本型別 集合結構 線性結構 樹狀結構和網路結構。包括順序儲存 鏈式儲存 索引儲存 雜湊儲存。這個時候,我們可以得出這麼個雜湊函式 f 0 0,f 1 1,f 20 20,這個是根據我們自己設定的直接定址來的。人數我們可以不管,我們關心的是如何通過關鍵字找到位址。例子 一 線性表 特點 首無前...