P4735 最大異或和(可持久化 trie)

2022-02-27 08:03:10 字數 1395 閱讀 5403

設 \(sum_i\) 表示前 \(i\) 個數的異或和,轉換那個式子為 \(sum_n \operatorname x \operatorname sum_i,i\ in [l-1,r-1]\)

其中的 \(sum_n \operatorname x \operatorname\) 是個定值,也就是找乙個 \(i\) 使得這個式子最大

由於這是異或運算,從高位向低位考慮,貪心的讓每一位盡量和 \(sum_n \operatorname x \operatorname\) 的結果不一樣

可以把這 \(n\) 個 \(sum\) 值插入到乙個 trie 上

就是如果第 \(pos\) 位結果是 \(k\),那麼如果 \([l-1,r-1]\) 中有乙個 \(sum_j\) 使得它的第 \(pos\) 位是 \(k \operatorname 1\),那麼就選他,答案加 \(2^\),否則選另乙個,答案不加

然後想看區間內某個位置上 \(1/0\) 的數有沒有,其實就是看這個位上是 \(1/0\) 的數的個數的字首和,這就用到了 trie 的可持久化,每插入乙個數時,對於某一位,把它所對應的那個數字的兒子(比如這個位置是 \(1\),就是son[1])開乙個新的記憶體,個數加一,另乙個兒子還是指向原來那個樹的兒子(同時個數也就不變)

其實就是 \(n\) 個根,每個根都對應乙個完整的樹,但這些樹會有一些節點是共用的

要注意在最前面插入乙個 \(0\),來應對 \(l=0\) 的情況,由於每個新插入的數的每一位都要開闢乙個新記憶體,所以空間是 \(o((n+m)\log a_i)\) 的

為了防止判斷空指標帶來的**細節增多和常數增大,用乙個自己設定的null來作為空指標

#include#include#include#include#include#include#include#define reg register

#define en puts("")

inline long long read()

while(c>='0'&&c<='9')

return y?x:-x;

}int n,m;

struct trdizhi[20000006],*root[600006],*null;

int tot=-1;

inline tr *new()

void build(tr *last,tr *tree,int num,int pos)

int ask(tr *left,tr *right,int num,int pos)

#define max 24

int main()

reg char c;reg int l,r;

while(m--)

else

} return 0;

}

P4735 最大異或和 可持久化Trie

n nn個數字,有操作 在末尾加入乙個數字x xx詢問 l,r l,r l,r 範圍內的乙個p pp使得ap ap 1 ap 2.an xa p oplus a oplus a oplus a oplus x ap ap 1 ap 2 an x的值最大。定義si s isi 表示字首異或和,那麼其實...

P4735 最大異或和 可持久化Trie

給定乙個非負整數序列 初始長度為 n 有 m 個操作,有以下兩種操作型別 a x 新增操作,表示在序列末尾新增乙個數 x 序列的長度 n 1 q l r x 詢問操作,你需要找到乙個位置 p 滿足 l le p le r 使得 a p oplus a p 1 oplus oplus a n oplu...

P4735 最大異或和 01可持久化Trie樹模板

原題 題解 觀察一下式子,將a陣列求乙個異或字首和,其實就是s n x s p 1 的最大值 p l,r 就是區間對乙個數的異或的最最大值。假設我們把這個區間放進trie字典樹中,對於乙個x的詢問,可以用貪心的思想,反著走找到最大值。但是確定出給定區間的trie樹,用類似於主席樹的思想,建一顆動態開...