可持久化資料結構的原理在於,每次修改創造乙個新節點作為根,對修改部分再創一條鏈,對於未修改部分直接連向上次修改連向的位置,這樣,就可以在較小的空間儲存每次修改時的狀態.
以可持久化字典樹為例
如果我們要加入cat,cap,rat,cute,等詞
第一步
然後,再插入第二個單詞
可以看到,新建一棵樹存當前的詞,然後連向之前已經有過的樹
第三第四個單詞
以上就是可持久化字典樹的內容
可持久化線段樹同理
每次修改新增一條,剩下的直接連向之前的
最大異或和( ) 洛谷p4735
每次將字首和的二進位制形式加入到0/1字典樹中
詢問時優先詢問與某關鍵值(x^s[n])相反的路徑
從高位到低位儲存和詢問
因為0/1字典樹是二叉的,所以連向上一段的已有子樹可以直接連線
陣列解釋
int trie[maxn*24]
[2],latest[maxn*24]
;//字典樹;當前結點向下傳遞的最後乙個字首和的位置編號
//位置編號就是指插入的順序編號
int s[maxn]
,root[maxn]
,n,m,tot;
//字首和;根據更改先後變化的根節點
以下是插入操作
void
insert
(int i,
int k,
int p,
int q)
//第i個字首和,二進位制從低到高第k位,p為上一段同深度端點,q為當前端點
int c=s[i]
>>k&1;
if(p) trie[q]
[c^1
]=trie[p]
[c^1];
//如果上一段有平行的對應結點則連線
trie[q]
[c]=
++tot;
//新建結點
insert
(i,k-
1,trie[p]
[c],trie[q]
[c])
;//插入下乙個結點
latest[q]
=max
(latest[trie[q][0
]],latest[trie[q][1
]]);
//向下最大的末位字首和位置編號
}
以下是完整**
#include
#include
#include
#include
#define r rein()
#define lr lrein()
#define ll long long int
#define ri register int
inline
int r
inline ll lr
using
namespace std;
const
int deviation=10;
const
int maxn=
3e5+deviation;
int trie[maxn*24]
[2],latest[maxn*24]
;int s[maxn]
,root[maxn]
,n,m,tot;
void
insert
(int i,
int k,
int p,
int q)
int c=s[i]
>>k&1;
if(p) trie[q]
[c^1
]=trie[p]
[c^1];
trie[q]
[c]=
++tot;
insert
(i,k-
1,trie[p]
[c],trie[q]
[c])
; latest[q]
=max
(latest[trie[q][0
]],latest[trie[q][1
]]);
}int
ask(
int now,
int val,
int k,
int limit)
intmain()
}return0;
}
可持久化資料結構
1.可持久化線段樹 可持久化陣列 最基礎的可持久化資料結構,每次修改開新的log個點即可。includeusing namespace std const int n 1e6 100 templatevoid rd t x templatevoid print t x struct segseg n...
可持久化資料結構
用vector實現可持久化 這題要求的是乙個支援區間查詢的可持久化資料結構。這裡使用vector巧妙地實現 pair用pair儲存時間戳以及當前時間的值,query的時候使用二分查詢即可。如下 1 include2 include3 include4 include5 define x first ...
可持久化資料結構維護可持久化陣列
首先我們要知道,undo 操作,也就是直接跳回前面的操作 歷史操作 然後跳回的地方到現在的地方這乙個區間的操作都不用管。這就是高階挑戰的思路 可持久化是指一種可以訪問歷史版本的資料結構 然後我們就可以知道,詢問歷史,又是陣列,也就是可持久化陣列。可持久化陣列的維護很簡單,我們可以開乙個 o n 2 ...