1. 程式人生 > 實用技巧 >NOIP--OI省選演算法之主席樹

NOIP--OI省選演算法之主席樹

主席樹是什麼

主席樹:是一種字首樹,通過一個地址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