主席樹(靜態)的輕鬆入門

 

主席樹入門

 

emmm…最近入門了主席樹, 感受其實不是很難, 主要理解了就很簡單了(畢竟代碼這麼短)html

主席樹的用處:

給出一個數列,求區間 l ~ r 之間的第 k 大值

主席樹的概念:

利用數列中 n 個數據創建 n 棵樹, 其中第 i 棵樹維護 1 ~ i 這個前綴內的數據信息 第 i 棵樹中的每一個節點都有其所表明的區間範圍(和線段樹同樣), 但這些節點所表明的區間範圍指的是值域範圍, 即每一個節點維護 1 ~ i 之間的所有節點中在此至於範圍內的數的個數

主席樹的創建

(圖片出自主席樹詳解 )c++

下面是一棵空樹(在代碼實現中能夠不建樹)
盜個圖git

以前說的主席樹的概念中, 主席樹是要對每一個節點 i 創建一棵維護前綴信息的樹.
可是對於每個前綴數列都建一棵樹所要使用的節點是 O(n logn )的.
因此… 真的如此樸素的建樹的話必然會爆內存.可是咱們仔細想一想以後能夠發現:
第 i 棵樹 和 第 i-1 棵樹中許多節點都是信息相同(即 在一棵樹中的位置相同且維護的數值相同)的類似節點, .
那麼咱們可不能夠考慮偷懶一點, 將上一棵樹的節點直接拿過來用呢?固然是能夠的, 圖以下.ide

0

下面還有一張, 是沒有重複利用節點的…森林吧 (圖中類似節點編號相同).spa

1

將相同編號的節點合併以後是這樣的:.net

2


主席樹的模板

 1 //by Judge
 2 #include<bits/stdc++.h>
 3 #define mid (l+r>>1)
 4 using namespace std;  5 const int M=2e5+111;  6 inline int read(){  7     int x=0,f=1; char c=getchar();  8     for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;  9     for(;isdigit(c);c=getchar()) x=x*10+c-'0'; 10     return x*f; 11 } 12 int n,m,q,cnt; 13 int a[M],b[M],t[M],sum[M<<5],L[M<<5],R[M<<5]; 14 void update(int las,int &now,int l,int r,int x){  //插入節點
15     if(!now) now=++cnt; sum[now]=sum[las]+1; if(l==r) return ; 16     // l==r直接返回, 不然向下新建改變了的節點, 沒改變的直接調用
17     if(x<=mid) R[now]=R[las],update(L[las],L[now],l,mid,x); 18     else L[now]=L[las],update(R[las],R[now],mid+1,r,x); 19 } 20 int query(int u,int v,int l,int r,int k){  //查詢 u ~ v 區間內第 k 大的數離散後的值
21     if(l>=r) return l; int x=sum[L[v]]-sum[L[u]]; 22     //這裏與二分查找樹相似
23     if(x>=k) return query(L[u],L[v],l,mid,k); 24     else return query(R[u],R[v],mid+1,r,k-x); 25 } 26 int main(){ 27     n=read(), q=read(); 28     for(int i=1;i<=n;++i) 29         b[i]=a[i]=read(); 30     sort(b+1,b+1+n); 31     m=unique(b+1,b+1+n)-(b+1); //排序並去重
32     int x,y,k; 33     for(int i=1;i<=n;++i) 34         k=lower_bound(b+1,b+1+m,a[i])-b, //離散
35         update(t[i-1],t[i],1,m,k); 36     while(q--) 37         x=read(), y=read(), k=read(), 38         printf("%d\n",b[query(t[x-1],t[y],1,m,k)]); //將離散前的值輸出
39     return 0; 40 }
主席樹

 

最後感謝 bzt 大佬的blogcode

同窗們bye ( ^_^ )/~~htm

相關文章
相關標籤/搜索