模板題在這裡洛谷2617。
閱讀本文需要有主席樹的基礎,也就是通過區間kth的模板題。
靜態整體kth:
sort一下找第k小,時間複雜度\(o(nlogn)\)。
動態整體kth:
權值線段樹維護一下,時間複雜度\(o(nlogn)\)。
靜態區間kth:
主席樹維護,時間複雜度\(o(nlogn)\)。
動態區間kth:
就是本次的標題。
回憶一下主席樹是如何維護靜態區間kth的。
建立可持久化線段樹後,利用字首和的思想查詢區間的kth。
所以我們想對區間kth帶修改操作,字首和是關鍵。
我們在維護普通字首和,支援查詢和修改操作時,用的是什麼資料結構呢?
所以這時候我們大致有乙個概念了,動態主席樹和主席樹在資料結構上已經多少有點不一樣了。
怎麼套是乙個問題,但簡單想想可以發現,我們在外層維護一顆樹狀陣列,樹狀陣列的每個節點(內層)維護權值線段樹(的根節點),可以解決這個問題。
查操作:
所以總的算下來時間複雜度在\(o(n(logn)^2)\)上。
接下來解決一下空間的問題。
我們知道線段樹的空間複雜度是\(o(4n)\)的,也就是\(o(n)\),樹狀陣列的複雜度為\(o(n)\),那麼如此算下來空間複雜度達到了\(o(n^2)\)。
思考一下怎麼優化?
我們剛剛計算的空間複雜度,基於對每個節點都把完整的權值線段樹開出來。
我們查詢/修改操作的規模是\((logn)^2\)級別的。
那是不是可以動態開點。
對於我們能訪問到的節點創立節點,對於不能訪問到的,就不管了。
附\(luogu2617\)**。
#includeusing namespace std;
const int maxn = 1e5+10;
int n, m, a[maxn], b[maxn<<1], len;
struct query
q[maxn];
//1e5的log大概在20左右 20*20=400
int sum[maxn*400];
int ls[maxn*400];
int rs[maxn*400];
int rt[maxn*400];
int tot;
void update_sgt(int &rt, int l, int r, int x, int val)
int mid = (l+r) >> 1;
if(x <= mid) update_sgt(ls[rt], l, mid, x, val);
else update_sgt(rs[rt], mid+1, r, x, val);
sum[rt] = sum[ls[rt]] + sum[rs[rt]];
}inline int lowbit(int x)
void update_bit(int pos, int x, int val)
///提取區間線段樹的根節點
int rt1[maxn], rt2[maxn], cnt1, cnt2;
void locate(int l, int r)
int ask(int l, int r, int k)
else
}int main()
char op[2];
for(int i = 1; i <= m; i++)
else
}//數值離散化
sort(b+1, b+1+len);
len = unique(b+1, b+1+len)-b-1;
for(int i = 1; i <= n; i++)
a[i] = lower_bound(b+1, b+len+1, a[i])-b;
for(int i = 1; i <= m; i++)
if(q[i].op) q[i].k = lower_bound(b+1, b+len+1, q[i].k)-b;
//建樹(動態開點形式)
for(int i = 1; i <= n; i++)
update_bit(i, a[i], 1);
for(int i = 1; i <= m; i++)
else
}return 0;
}
主席樹(區間第k小)
k th number 求區間內第k小的數。主席樹的板子題 主席樹左子樹存小值,右邊大值,用sum記錄一下子樹節點個數。對 l,r 的查詢區間,root r root l 1 可得出 l,r 的差值,也就是大小的個數 include include include include include i...
主席樹 區間第k小
主席樹 權值線段樹 可持久化 權值線段樹 在此處指各個數字在某個區間內出現的次數 那麼第一棵權值線段樹會記錄 1,1 的數字出現次數 第n棵權值線段樹會記錄 1,n 的數字出現次數 例 數列為110001 第一棵權值線段樹記錄為tree1 0 0 tree1 1 1 第二棵權值線段樹記錄為tree2...
主席樹 靜態區間第k小
這是個非常經典的主席樹入門題 靜態區間第k小 資料已經過加強,請使用主席樹。同時請注意常數優化 如題,給定n個整數構成的序列,將對於指定的閉區間查詢其區間內的第k小值。輸入格式 第一行包含兩個正整數n m,分別表示序列的長度和查詢的個數。第二行包含n個整數,表示這個序列各項的數字。接下來m行每行包含...