題意:
給你一棵樹,有邊權,定義兩點之間的價值為這連線兩點的這條路徑上所有邊權的異或和,如1→2
1\rightarrow 2
1→2所經過的邊權為1,2
,31,2,3
1,2,
3,那麼1→2
1\rightarrow 2
1→2的權值就為1⨁2
⨁3=3
1\bigoplus2\bigoplus3=3
1⨁2⨁3=
3,請你求出哪兩個點的價值最大,輸出這個價值。
其實,有乙個非常重要的技巧,就是在異或中,相同的兩個數異或起來為0,而0異或任何數字都沒有影響,所以我們可以將兩個點a,b
a,ba,
b之間的路徑的異或和看作a→r
oota\rightarrow root
a→root
的異或和異或上b→r
ootb\rightarrow root
b→root
的異或和(root為樹的根),那麼此時lca
(a,b
)→ro
otlca(a,b)\rightarrow root
lca(a,
b)→r
oot這段多餘的值就被異或了兩次,就消除掉影響了,所以這個答案就是a,b
a,ba,
b的價值。
那麼我們預處理處所有點到根的路徑異或和,然後只需選兩個出來,使其異或最大即可。
那麼關於一堆數中選兩個數出來異或最大,由於和二進位制位有關,所以我們可以用01-trie樹,也就是普通的trie樹,字符集只有0,1。
那麼舉個例子:
對於1 ,2
,3,4
,5,6
1,2,3,4,5,6
1,2,3,
4,5,
6這堆數,建出來的01-trie樹就是這個樣子的:
所以我們接下來建出來後有兩種方式求答案:
我們知道,求乙個數與一堆數中的乙個異或最大可以直接把這個數從高位到低位貪心的在01-trie上走一遍,就可以知道答案了,複雜度是o(l
ogv)
o(lo**)
o(lo**
)(v為最大權值),那麼將n
nn個數全部帶進去走一遍就可以得到答案,複雜度是o(n
logv
)o(nlo**)
o(nlog
v)的。我們直接用兩個指標在trie樹上,從高位到低位走,貪心,每次能走相反的就走相反的,然後取最大的走出來的值即可,複雜度為o(n
)∼o(
2n)o(n)\sim o(2n)
o(n)∼o
(2n)
我寫的第二種方法,第一種的**可以隨便去網上找,都有。
#include
#include
#include
using
namespace std;
const
int m=
1e5+10;
int n,val[m]
;struct ssss(
int a,
int b,
int c):to
(a),
last
(b),
len(c)
}g[m<<1]
;int head[m]
,cnt,maxv,lg;
void
add(
int a,
int b,
int c)
void
dfs(
int a,
int b)
}int son[2]
[m<<4]
,tot;
void
insert
(int a)
}int ans;
void
find
(int a,
int b,
int v,
int bit)
else
}else
if(son[1]
[a]&&son[0]
[b])
//走(1,0),(0,1),如果沒法的話再走(1,1),(0,0),這裡是個貪心if(
!had)
if(son[1]
[a]&&son[1]
[b])}}
//由於最多會有2n個節點,最壞的情況是將其全部遍歷一次,所以複雜度為o(n)的
}int a,b,c;
intmain()
dfs(1,
0);for
(lg=1;
(1ll
<
++lg)
;//小心1<<32爆int,我開始寫錯了tle了好幾次
for(
int i=
1;i<=n;i++
)insert
(val[i]);
//但是遺憾的是構建的複雜度還是o(nlo**)的
find(0
,0,0
,lg)
;printf
("%d\n"
,ans)
;return0;
}
AcWing 144 最長異或值路徑(Trie)
題目大意 一棵樹,邊有權值。現在定義路徑的值為路徑中邊的權值的異或值,求異或值最大的路徑。題解 從a到b路徑的異或值 a到根結點的異或值 b到根結點的異或值。這樣求出每個點到根結點的異或值,然後從n個數中選出異或值最大的數就可以。把n個數插入trie樹中做。include include inclu...
最長異或路徑
題目鏈結 戳我前置知識 什麼是異或?如果二進位制下同一位不相同,則為 1 否則為 0 trie樹 基本位運算 對於同一條邊異或兩次,相當於沒有進行異或,我們將dis i 表示為從i點到根節點的路徑異或和。則問題轉化為了求兩點的dis異或最大值 貪心的想,對於乙個數x,我們對於dis i x最大,則每...
題解 P4551 最長異或路徑
給定一棵 n 個點的帶權樹,結點下標從 1 開始到 n 尋找樹中找兩個結點,求最長的異或路徑。異或路徑指的是指兩個結點之間唯一路徑上的所有邊權的異或。include include define m 200070 define n 5000070 using namespace std struct...