01字典樹 OR問題

2021-09-03 06:58:11 字數 1556 閱讀 5890

01字典樹

用途:解決區間異或和之類的問題

異或的性質:

1. 交換律

2. 結合律,即(a^b)^c = a^(b^c))

3. 自反性,即x^x=0

4. x^0=x

有上述性質,對於區間異或和要知道此性質xor[l,r] = xor[1,l-1] ^ xor[1,r]

注意:int型別1<<31會溢位

區間異或和的題目:比如給一組數列求l,r,要求[l,r]是所有區間中異或和最大

由x xor x = 0 ; 0 xor y = y;所有【l,r】=【1,r】xor【1,l - 1】。這樣在一顆加入了r 前的所有字首異或和的01字典樹上查詢【1,r】就能得到以r為右邊界的最大異或和。簡單來說,就是先把數列的每個數變成字首異或和,這樣求區間中異或和最大就變成了找兩個數異或和最大(因為【1,r】得到以r為右邊界的異或和,【1,l-1】就能得到以l-1為右邊界的異或和,易得【l,r】=【1,r】xor【1,l - 1】的區間異或和值)。每個數字先貪心搜尋,再插入,就能實現其跟前面出現過的都進行比較了,如全部插入再全部搜,容易出現重複,時間會翻倍。

poj3764

要求在樹中找兩個結點,且兩個結點之間路徑唯一,求最長的異或路徑。很明顯不能用暴力,o(n2)時間複雜度100000個點。首先我們需要知道乙個性質:a^b = (a^c)^(b^c),這樣就可以考慮找出a與b公共的c,實際上就是求出從根節點到每個節點的異或值,這樣任意兩個點做異或,即是他們之間的異或路徑(相同部分異或抵消了)。先遍歷dfs遍歷一遍,找出所有結點到樹根的路徑異或值,則問題就轉化成了求這些點中任意兩個點的異或值,接下來就很簡單了,將dfs所得的每個點的異或值轉化成二進位制數存進字典樹,然後從高位至低位對字典樹進行貪心,找出最大的那個值。這裡跟上一題一樣,每個數字先貪心搜尋,再插入,就能實現其跟前面出現過的都進行比較了,如全部插入再全部搜,容易出現重複,時間會翻倍。字典樹的時間複雜度為o(31*n),dfs時間複雜度為o(n)。

#include using namespace std;

typedef long long ll;

const int maxn = 100000 + 5; //集合中的數字個數

int ch[32 * maxn][2]; //節點的邊資訊

ll value[32 * maxn]; //節點儲存的值

int node_cnt; //樹中當前節點個數

inline void init()

inline void insert(ll x) //上面設val為0,因多組詢問,可能上一樣例是葉子

cur = ch[cur][idx];//遞迴下一層,每層乙個位,32位即32層,每個結點有01兩兒

}value[cur] = x;//最後的節點插入value,即葉子存值,每次詢問時貪心搜到葉子(見下文)

}inline ll query(ll x)

return value[cur]; //返回要異或的葉子編號

}int main()

字典樹 與 01字典樹

字典樹可以降低空間複雜度 01字典樹可以降低時間複雜度。字典樹 又稱單詞查詢樹,trie樹,是一種樹形結構,是一種雜湊樹的變種。典型應用是用於統計,排序和儲存大量的字串 但不僅限於字串 所以經常被搜尋引擎系統用於文字詞頻統計。它的優點是 利用字串的公共字首來減少查詢時間,最大限度地減少無謂的字串比較...

01字典樹 小結

為了做13年南京網路賽的一道題 學了這個01字典樹 看了別人的模板 之後切了幾道水題 現在總結一下 01字典樹的實現可以看成是把乙個數的二進位制字元化後插入到一顆一般的字典樹中 比如在01字典樹種插入3時 相當於在字典樹中插入00 00011 一共33為,這個根據具體實現不同 查詢最大異或值的時候我...

01字典樹模板

題意 輸入n n次操作 x 插入x x 刪除x x 查詢已經插入的某個數與x異或的最大異或和思路 01字典樹模板題 遇到這題剛好可以更新一下自己的模板 以前的太醜了 ps 這題有個坑點是字典樹為空的情況下可能會查詢,所以開始的時候先插入乙個0 code include using namespace...