可持久化線段樹(主席樹)

2022-03-16 19:58:04 字數 1216 閱讀 4572

動態開點建樹即可。

void build(int &o,int l,int r) 

build(ls[o],l,mid);

build(rs[o],mid+1,r);

return;

}

左右子節點繼承上一版本即可,注意$sum$應當較上一版本$+1$。

void update(int &o,int l,int r,int pre,int x) 

if(x<=mid)

else

}

注意是用右邊界的左子節點減去左邊界的左子節點

int kth(int l,int r,int x,int y,int k) 

int tmp=sum[ls[y]]-sum[ls[x]];

if(k<=tmp)

else

}

板子我是用$namespace$寫的,放在這方便以後用。

注意線段樹的陣列開40倍。

#define n 200010

#define mid ((l+r)>>1)

int n,m,siz,ind;

int rt[(n<<5)+(n<<3)],ls[(n<<5)+(n<<3)],rs[(n<<5)+(n<<3)],sum[(n<<5)+(n<<3)],a[n],b[n];

namespace persistence_segment_tree

return; }

void build(int &o,int l,int r)

build(ls[o],l,mid);

build(rs[o],mid+1,r);

return; }

void update(int &o,int l,int r,int pre,int x)

if(x<=mid)

else }

void init() }

int kth(int l,int r,int x,int y,int k)

int tmp=sum[ls[y]]-sum[ls[x]];

if(k<=tmp)

else }

void solve()

return;

}}

主席樹(可持久化線段樹)

我真弱。連主席樹都不會。主席樹相當於多個線段樹,由於相鄰兩棵線段樹的節點的值只有少許不同,因此可以對於和前一棵樹一樣的子樹乙個指標指過去,無需操作,這樣每棵樹o logn 總複雜度o nlogn 以下是區間k大 include include include define n 100005 defi...

主席樹 可持久化線段樹

首先要學會普通的線段樹,然後理解權值線段樹,而主席樹就是多個權值線段樹 我自己的理解 但是這多個權值線段樹之間有公共部分,節約了空間。它一開始是乙個空樹,後來逐個添數,記錄新增的這個數在那個範圍內,並 1,顯然它每次只更新了一條鏈,其他不需要變,這樣就有了多個版本的線段樹。如果求 l,r 範圍內第k...

可持久化線段樹(主席樹)

qwq我大概又是機房最後乙個學主席樹的了吧 其實之前一直都在講 只是沒做題 做了幾道以後發現都是乙個套路qwq關鍵就是能不能看出來要用主席樹 主要可以解決 靜態 動態區間第k大 樹上也可以 一些有關區間的帶某些限制的詢問 如出現次數等 先把模板粘上來 include include include ...