10 2 異或樹經驗

2022-04-06 04:14:30 字數 2041 閱讀 9274

首先我們要知道,要求出任意兩點之間的路徑異或和,

e.g.1:g——e:

可以得出g——e的路徑異或和等於g——a的異或和異或上e——a的路徑異或和。

證明:a——g的路徑異或和:abbddg;

a——e的路徑異或和:ac^ce;

把兩個異或起來就是abbddgacce;

e.g.2:g——h(換兩個有重複的試試?

可以得出g——h的路徑異或和等於g——a的異或和異或上h——a的路徑異或和。

證明:a——g的路徑異或和:abbddg;

a——h的路徑異或和:abbddh;

把兩個異或起來:dg^dh

這其實就相當於求abb=?

我們知道,異或就是按位不進製加法:

1^1=0;

1^0=1;

0^1=1;

0^0=0;

因為是二進位制,所以說連續進行兩次不進製加法就又返回了原值。

然後就可以得到70%的分數。

要得到100%的分數,我們就要使用一種叫01字典樹的做法.

就是把每乙個數都轉換為二進位制,然後轉換為一顆字典樹,從高位到低位貪心出最大異或和即可。

如圖:

ps:左下角被擋住的兩個單詞是inn和int

這是inn, int, at, age, adv, ant這六個單詞組成的字典樹,我們可以看到,他們每乙個單詞都有共同開頭幾個字母。

所以運用一棵字典樹,就可以巧妙的按照從跟到其他任意乙個節點的方案走出每乙個單詞。

到了數字裡:

因為前文已經說明,要求出任何兩個點之間的異或和都可以轉換成兩者與根之間的關係。

所以,也就可以構造成一顆:01字典樹。

其變化就是把字母替換成了0或1,因為單詞是又一些字母組成,而乙個10進製的數是由一些0和1組成一樣。

所以說這樣轉換後,就可以求貪心求最長異或和了。

比如從根開始找,一直找1就行。

#include

#include

#include

#include

#include

#include

#define maxn 100010

using

namespace std;

struct edgee[maxn*2]

;int point[maxn]

,cnt,n,xorval[maxn]

;int t[maxn*32]

[2],root,size,ans;

bool vis[maxn]

;void

addedge

(int x,

int y,

int val)

void

dfs(

int x)}}

void

insert

(int val)

}void

init()

void

query

(int val)

} ans=

max(ans,sum);}

intmain()

dfs(0)

;//深搜

for(

int i=

0;i)insert

(xorval[i]);

for(

int i=

0;i)query

(xorval[i]);

printf

("%d\n"

,ans);}

}

10 2 異或樹經驗

首先我們要知道,要求出任意兩點之間的路徑異或和,e.g.1 g e 可以得出g e的路徑異或和等於g a的異或和異或上e a的路徑異或和。證明 a g的路徑異或和 abbddg a e的路徑異或和 ac ce 把兩個異或起來就是abbddgacce e.g.2 g h 換兩個有重複的試試?可以得出g...

異或 異或相關

感謝 morning glory 贊助 異或異 或 de scri ptio ndes crip tion 給定 l,r l,r,求 i lr j lr i ji l r j l r i jl,r 1 09l,r 1 09 s olut ions olut ion 假設l 1,r 4l 1,r 4,...

字典樹處理《異或》

題目 問題很簡單,現在有乙個陣列a1,a2,a3 an。你的任務就是找到乙個連續子段 l,r 使得al al 1 ar達到最大。input 多組輸入,每組有兩行。第一行有乙個整數n 1 n 10 5 表示陣列的元素個數。第二行有n個元素,依次表示陣列的元素。0 ai 10 6 output 每組輸出...