首先我們要知道,要求出任意兩點之間的路徑異或和,
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 每組輸出...