可持久化字典樹

2022-07-23 23:21:23 字數 1332 閱讀 8605

以每個結點為根,建一顆字典樹(內容為1到i的值)。這樣之後,做差後,即為一段區間或是一段路徑。

可以發現,如果裸著建,不僅要消耗很多的時間,更是要消耗很多的空間。考慮以i為根的字典樹和以(i-1)為跟的字典樹的異同。

可以發現,在當前以i為根的字典樹上減去a[i],就是(i-1)的字典樹了。所以,我們可以將除了a[i]之外的結點都連到(i-1)的樹上。

當然,i-1的樹也是從i-2的樹上引用過來的。

這樣之後,會出現乙個問題。比如,a[i-1]的值與a[i]的值相同,那麼我們到底要不要跟新呢?還是直接將root[i]全部指向root[i-1]?

還是之前的做法。除了a[i]的值,其他的值全部引用前面的,將a[i]跟新root[i]。

這樣做完之後,可以發現,如果不加以區分,root[i]和root[i-1]的樹一模一樣,直接做差之後不就沒有了。可是事實上,在【i,i】這給區間內,有乙個數的值為a[i]。

所以我們用乙個sum陣列加以區別,也就是說,如果當前的root的結點是引用前面的,那麼sum不變。否則(就是a[i]跟新的部分),sum[root[i]]=sum[[root[i-1]]+1。a[i]這個數的每個位置都是之前的+1。

這樣我們在判斷區間的時候,就可以拿sum[root[r]]-sum[root[l-1]]。如果大於0,說明在root[l-1]之後,被跟新過,所以可以取。如果sum值相同,代表root[r]中的那部分是直接引用的root[l-1]中的那部分,這個區間內沒有跟新過,所以無法取。

//要查詢的是sum[n]^sum[k-1]^x 最大。

//從k開始異或,那麼l-1<=k-1<=r-1 所以看以r-1為根的樹是在以l-2為根的樹上跟新過

// 所以應該是root[r],root[l-1]

#include"stdio.h"

#define n 30050000

int tree[n][2];

int root[n];

int l;

int sum[n];

int d[40];

int cnt;

void split(int k)

for (i=l+1;i<=27;i++) d[i]=0;

return;

}void build(int x,int &y)

}int query(int x,int y) else

} return ans;

}char s[10];

int main()

for (i=1;i<=m;i++) else

}}

模板 可持久化字典樹

made by xiper updata time 2015 12 8 test status 使用前呼叫初始化函式 init 同時 root 0 0 struct trie persistent tree triesize 獲取字符集雜湊編號 必須在 0 lettersize 之內 inline ...

dfs序 可持久化字典樹

query on a tree 題意 有一顆樹,有n個節點,每個節點都有權值,有q次詢問,每次詢問以u為根的子樹節點權值中異或x結果最大的值。題解 首先解決u為根子樹節點的問題,直接dfs序,解決異或,用字典樹,但是同時用的話,就需要用可持久化字典樹,其實就是字首樹。這題學習到一波可持久化字典樹。i...

bzoj4546 可持久化字典樹

可持久化字典樹模板題。把每個數轉換成二進位制建立字典樹,按照下標建立可持久化字典樹,存一下子樹中點的個數就行了。1 include2 include3 include4 include5 using namespace std 6 inline char nc 12return p1 13 14 i...