模板 區間第k小

2022-02-23 21:14:46 字數 2667 閱讀 5987

我實在是太弱了現在才會這個東西qaq。

主席樹做法。

一張關於主席樹的無字說明

線段樹\(2\)是只單點修改了實心酒紅色點的線段樹\(2\),線段樹\(2\)中的藍色節點實際上就是線段樹\(1\)的藍色節點,我們只是把位址複製過來了。

我們多開了乙個線段樹,但是節點數量卻只多了\(log\)層,那麼對於\(n\)的歷史版本保留就提供了\(o(nlogn)\)的資料結構啦。

具體**怎麼實現?我研究了一下,發現實際寫出來的**和大家常寫的**是一樣的。實現其實非常簡單,只需要在普通線段樹上稍微修改一下。

如何訪問歷史版本?我們可以開乙個\(rt(i)\)陣列表示\(i\)號版本的根節點的編號,對於線段樹每個節點我們要記錄\(seg_l,seg_r,data\),遞迴時只要訪問\(seg_\)的值就好了,不需要很大的修改。

其實我還想問乙個問題,就是我發現這種主席樹支援單點修改,區間查詢,但是我想問如果是區間修改,而且是\(n\times n\)的修改怎麼辦?因為我發現修改乙個點就一定會產生新的\(n\)個節點了。

實際上主席樹就是讓整個線段樹有了兩維下標,所以對於什麼二維數點啊什麼什麼之類的也有用。

這個問題以後再解決,那麼有了主席樹工具之後怎麼解此題?

不是兩維下標嗎?建立乙個下標是值域和位置的線段樹(按照給的序列的順序建立主席樹,主席樹儲存的東西是值域內有多少個數),然後區間的限制可以直接是\(rt_r-rt_\)很方便地查詢。

實際上,主席樹教會我們如何弄乙個可持久化陣列!有了可持久化陣列,什麼可持久化資料結構不行!平衡樹呢:)

#includeusing namespace std;typedef long long ll;

#define rp(t,a,b) for(register int t=(a),edd=(b);t<=edd;++t)

#define midd register int mid=(l+r)>>1

#define tmp template < class ccf >

#define lef l,mid,seg[pos].l

#define rgt mid+1,r,seg[pos].r

tmp inline ccf qr(ccf b)

tmp inline ccf max(ccf a,ccf b)

int main()

rp(t,1,m)

return 0;

}

還有一道模板題,也放進來吧

#includeusing namespace std;typedef long long ll;

#define drp(t,a,b) for(register int t=(a),edd=(b);t>=edd;--t)

#define rp(t,a,b) for(register int t=(a),edd=(b);t<=edd;++t)

#define erp(t,a) for(register int t=head[a];t;t=e[t].nx)

#define midd register int mid=(l+r)>>1

#define tmp template < class ccf >

#define lef l,mid,sl[pos]

#define rgt mid+1,r,sr[pos]

const int maxn=1e6+5;

char buf[maxn], *p1, *p2;

inline char gc()

tmp inline ccf qr(ccf b)

tmp inline ccf max(ccf a,ccf b)

tmp inline ccf min(ccf a,ccf b)

tmp inline ccf max(ccf a,ccf b,ccf c)

tmp inline ccf min(ccf a,ccf b,ccf c)

tmp inline ccf read(ccf* _arr,int _n)

//----------------------template&io---------------------------

int seg[maxn*81];

int data[maxn*81];

int sl[maxn*81];

int sr[maxn*81];

int rt[maxn];

int cnt;

int n,m;

void build0(int l,int r,int pos)

sl[pos]=++cnt;sr[pos]=++cnt;midd;

build0(lef);build0(rgt);

}void build(int last,int k,int l,int r,int pos)midd;

if(k<=mid)

else

}void upd(int last,int k,int l,int r,int pos)midd;

if(k<=mid)

else

}int main()

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小的問題的時候只會區間sort,後來才掌握了一些解決此類問題的方法。區間第k小有的題目帶修改有的不帶修改,不論是什麼,都有對應的解決方法。1.我們可以分塊。分成根號n塊,塊內排序。對於每次查詢l,r我們二分答案 二分乙個值,統計區間內比他小的個數 對於不完整的區間,我們掃一遍統計,對於...