主席樹求區間第k大

2021-09-25 13:37:28 字數 1242 閱讀 8486

主席樹是可持久化線段樹,維護(權值個數)線段樹的字首和。相當於對每個區間[1,i]建立n顆線段樹。

我們用乙個區間內的數的出現個數建線段樹,所以資料大小較大時一般進行離散化。

建的是權值線段樹,即用數值作為區間,每個節點存該數出現的次數,所以query返回的其實是離散後的陣列b的下標idx,最終結果為b[idx]

時間複雜度分析:離散化:o(n logn)

統計並插入的複雜度是o(n logn+n logn)=o(n log⁡n)

詢問的複雜度是o(n logn)

theme:給定n個數,q次詢問,每次求區間[l,r]中從小到大排序後第k個數。1 <= n <= 100 000, 1 <= q <= 5 000,1 <=l <=r<= n, 1 <= k <= j - i + 1

solution:主席樹裸題

//theme:給定n個數,q次詢問,每次求區間[l,r]中從小到大排序後第k個數。1 <= n <= 100 000, 1 <= q <= 5 000,1 <=l <=r<= n, 1 <= k <= j - i + 1

#include #include#include#define midd (l+r)/2

using namespace std;

typedef long long ll;

const int n = 200010;

int n, q, sz, cnt = 0;

int a[n], b[n], t[n];//a為原陣列,b為排序離散化陣列,t[i]為(值)[1,i]的根節點

int sum[n<<5], l[n<<5], r[n<<5];

inline int build(int l, int r)

return rt;

}inline int update(int pre, int l, int r, int x)

return rt;

}inline int query(int u, int v, int l, int r, int k)//返回下標,即<=k個數

int main()

sort(b+1, b+1+n);

sz = unique(b+1, b+1+n)-b-1;

t[0] = build(1, sz);

for (int i = 1; i <= n; i ++)

while (q --)

}return 0;

}

區間第k大(主席樹)

學了一下主席樹模板題,當初看了網上的主席樹講解都沒有看懂,後面看了嗶哩嗶哩的uestc的主席樹,終於看懂了思想。每次更新的複雜度都為logn。每次更新的話就是對要更新的點路徑上的點重新更加乙個,然後進行對沒有影響的那些進行連邊。然後用乙個root記錄每乙個線段樹的根節點下標。include incl...

主席樹區間第K大

主席樹的實質其實還是一顆線段樹,然後每一次修改都通過上一次的線段樹,來新增新邊,使得每次改變就改變logn個節點,很多節點重複利用,達到節省空間的目的。1.不帶修改的區間第k大。hdu 2665 模板題 1 include2 using namespace std 3 define fopen fr...

區間第k大的數 主席樹

套主席樹求區間第k小的數的模板,然後求區間 l,r 第k大的數就等於求區間 l,r 第r l 1 k小的數 下標從1開始 區間第k小值問題 有n個數,多次詢問乙個區間 l,r 中第k小的值是多少。查詢區間 l,r 中的第k小值 我們按照從1到n的順序依次將資料插入可持久化的線段樹中,將會得到n 1個...