模板鏈結
可持久化線段樹是一種可持久化結構,需要知道的前導知識有:線段樹、權值線段樹、離散化、線段樹的動態開點。說實話,當蒻苟我做了那麼多**的線段樹後發現,可持久化線段樹(僅限模板)還是很好寫的。
什麼叫可持久化?
可以想象,有乙個線段樹,他除了可以進行普通的查詢修改操作,還可以記錄歷史版本,即,我們可以調取任意修改次數時的狀態。我們這時可以想象乙個樸素的方法完成這個操作:
對於每次修改,我們都將我們建好的這棵樹整體複製乙個副本,然後我們在這個副本上修改。我們知道線段樹的空間複雜度為o (n)所以對於m次查詢,就是 o(nm),從空間上就**了。時間更不要說了。
這是就靠我們的動態開點技術了。
如果我們想修改3號節點。我們易知,pushup操作遍及下圖中的綠色節點,其他節點不涉及。
依次特性,我們每次創立新節點時候,知創立更改的節點,鏈結到原樹上:
這樣的化,空間複雜度降為o(nlogn)時間複雜度o(logn)。
概念理解完,看題。這個題的意思是讓我們查詢區間中的第k小的值。按照發明人的意思:對於乙個序列,我們每次建立乙個字首的權值線段樹。即,我們建立維護[1, r],(1<= r <= n)區間的權值線段樹,則我們定每乙個權值線段樹為本可持久化線段樹中的乙個歷史版本。我們通過字首和思想。我們想想要查詢[l,r]中值為k的數量。則,肯定為[1, r]中k的數量減去[1, l-1]的k的數量。於是,我們每次查詢r版本l-1版本的權值線段樹的k的數量,然後結合權值線段樹基本查詢方式。可以解出答案。
詳細實現過程請看**注釋。
下面是模板**:
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
using
namespace std;
const
int n =
2e5+5;
int root[n]
, cnt;
int lisan[n]
;int su[n]
;int mx;
// 先看main函式。
struct node
tr[n<<5]
;inline
intgetn
(int g)
void
change
(int l,
int r,
int&p,
int pre,
int v)
intask
(int l,
int r,
int l,
int r,
int k)
intmain()
sort
(lisan+
1, lisan+n+1)
; mx =
unique
(lisan+
1, lisan+n+1)
- lisan;
//離散化過程
for(
int i =
1; i <= n; i++
)change(1
, mx-
1, root[i]
, root[i-1]
,getn
(su[i]))
;//root[i]是指第i個歷史版本的權值線段樹的歷史版本根節點編號
//從1到mx-1的值域,以root[i-1]權值線段樹為原型,插入su[i],建立root[i]的權值線段樹。
while
(m--
)return0;
}//確實比那些**線段樹好寫吧 2333333
ps.change ask函式的l,r形參是值域範圍,不是該節點的左右孩子,更不是區間的範圍!另一道題。super mario hdu - 4417
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
using
namespace std;
const
int n =
1e5+5;
struct node
tr[n<<5]
;int su[n]
;int lisan[n]
;int root[n]
;int mx, _cnt, cnt, n, m;
inline
intgetn
(int x)
void
change
(int l,
int r,
int pre,
int&p,
int v)
intask
(int l,
int r,
int r,
int l,
int k)
void
print
(int p,
int l,
int r)
intmain()
printf
("%d\n"
,ask(1
, mx-
1, root[r+1]
, root[l]
, gg));}}}
洛谷P3834 可持久化線段樹 主席樹 模板
題目 無法忍受了,我要寫主席樹!解決區間第 k 大查詢問題,可以用主席樹,像字首和一樣建立 n 棵字首區間的權值線段樹 然後 n 棵線段樹可以共用一些節點 線段樹的 sum 可以相減,利用這個查詢即可 什麼嘛,主席樹也沒我想得那麼難 蠻簡單的 如下 include include include i...
洛谷P3919可持久化線段樹
有了可持久化陣列,便可以實現很多衍生的可持久化功能 例如 可持久化並查集 如題,你需要維護這樣的乙個長度為 n 的陣列,支援如下幾種操作 在某個歷史版本上修改某乙個位置上的值 訪問某個歷史版本上的某一位置的值 此外,每進行一次操作 對於操作2,即為生成乙個完全一樣的版本,不作任何改動 就會生成乙個新...
洛谷3834 可持久化線段樹(主席樹模板)
主席樹經典問題,靜態查詢區間第k大數。拖了很久都沒有寫的模板。結果差不多此次 你賽都考,痛定思痛後,決定好好研究下。主席樹可以近似理解為權值線段樹的字首和的形式,詳細講解可參考wcr寫的主席樹講解 傳送門。回到該題,因為不涉及修改操作,所以我們建立n棵權值線段樹,先將資料離散化,這樣主席樹的權值就在...