NOIP--OI省選演算法之主席樹
阿新 • • 發佈:2020-11-02
主席樹是什麼
主席樹:是一種字首樹,通過一個地址root[i]−>root[i−1]來實現的;
建樹
如上圖所示,我們在插入元素的時候分別為每一個元素都給它建一個樹
void init(int &p,int l,int r){ p=++tot; T[p].v=0; if(l==r)return;
int mid=l+r>>1; init(T[p].l,l,mid); init(T[p].r,mid+1,r); } void insert(int &p,int l,int r,int x,int pre){ p=++tot; T[p]=T[pre];//繼承上一個樹的資訊(像字首和一樣) T[p].v++;//加上本節點的資訊 if(l==r)return;
int mid=l+r>>1;
if(x<=mid)insert(T[p].l,l,mid,x,T[pre].l); else insert(T[p].r,mid+1,r,x,T[pre].r); }
查詢
由於主席樹為字首樹,故我們可以通過查詢不同時期的樹來蒐集資訊做到多維護一維資訊的效果
int query(int root1,int root2,int l,int r,int k){
if(l==r)return l; //由於這是一個字首樹,我們通過把id1,id2 int v1=T[T[root1].r].v;
int v2=T[T[root2].r].v; //蒐集兩個時期的資訊 int v=v2-v1,mid=l+r>>1;
if(k<=v)return query(T[root1].r,T[root2].r,mid+1,r,k);
return query(T[root1].l,T[root2].l,l,mid,k-v); }
綜上
struct Tree{
struct node{int l,r,v;}T[M<<4];
void init(int &p,int l,int r){ p=++tot; T[p].v=0;
if(l==r)return;
int mid=l+r>>1; init(T[p].l,l,mid); init(T[p].r,mid+1,r); } void insert(int &p,int l,int r,int x,int pre){ p=++tot; T[p]=T[pre];//繼承上一個樹的資訊(先字首和一樣) T[p].v++;//加上本節點的資訊 if(l==r)return;
int mid=l+r>>1;
if(x<=mid)insert(T[p].l,l,mid,x,T[pre].l); else insert(T[p].r,mid+1,r,x,T[pre].r); } int query(int id1,int id2,int l,int r,int k){ if(l==r)return l; //由於這是一個字首樹,我們通過把id1,id2 int v1=T[T[id1].r].v;// int v2=T[T[id2].r].v;
int v=v2-v1,mid=l+r>>1;
if(k<=v)return query(T[id1].r,T[id2].r,mid+1,r,k);
return query(T[id1].l,T[id2].l,l,mid,k-v); } }CT;
NOIP資訊學視訊地址
視訊地址
連結:https://pan.baidu.com/s/1tHo1DFMaDuMZAemNH60dmw
提取碼:7jgr