P4551 最长异或路径 Trie经典应用 bitset应用
P4551 最长异或路径 Trie经典应用 bitset应用
bitset使用
一个长度为\(N\)的bitset下标编号为\([0,N)\)
进行单点修改时,可以直接访问位置并且赋值
\[s[pos] = x;
\]
bitset重载了<< 和 >> 输入输出流,可以使用cin或者cout输入输出一个bitset的所有元素
注意bitset的输出方式
std::cin >> s; // 1101
std::cout << s << std::endl; // 000001101
bitset可以转化为string型,unsigned long long型,函数名to_string(),to_ullong()
成员函数
reset
s.reset();
将容器清空
set
s.reset();
s.set() //11111111
s.set(3,false) //11110111
s.set(3) //11111111
test
test有一个参数pos,返回一个bitset内第pos位的值。
any
bitset有一个成员函数为any,返回一个布尔量。若bitset内部存在一位的值为1,则返回true,否则返回false:
s.clear();
bool k = s.any(); //k is false
s[1] = true;
k = s.any() //k is true
count
count返回一个bitset内1的个数,是一个无符号整形:
s.reset();
int k = s.count(); // k is 0
s[1] = true;
k = s.count(); // k is 1
题意
给定一棵树和边权,求两点\(u,v\)使得两点的路径异或值最大。
\[1 \leq n \leq 1e5\\
0 \leq w \leq 2^{31}
\]
分析
我们发现两点的路径异或等于两点分别到根的路径异或值相异或(LCA到根的异或抵消)
那么只要DFS出了根到该点的异或值,问题就转化为了\(n\)个值,问其中异或值最大的两个值的异或,这是经典的Trie上贪心异或问题。
只需要把每个数从高位开始贪心插入Trie,枚举每个数然后再Trie上贪心走反的边即可。
复杂度O(w*n)
代码
struct Trie{
int now = 1;
int ch[100000 * 31][2];
//vector<vector<int>> ch;
//Trie():ch(100000 * 31,vector<int>(2,0)) {}
bitset<32> st;
void insert(int x){
st.reset();
int cnt = 0;
int cur = 1;
while(x){
st.set(cnt,x % 2);
x /= 2;
cnt++;
}
for(int i = 30;i >= 0;i--){
if(ch[cur][st.test(i)] == 0)
ch[cur][st.test(i)] = ++now;
cur = ch[cur][st.test(i)];
}
}
int get(int x){
st.reset();
int cnt = 0;
int cur = 1;
int res = 0;
while(x){
st.set(cnt,x % 2);
x /= 2;
cnt++;
}
for(int i = 30;i >= 0;i--){
if(ch[cur][!st.test(i)])
cur = ch[cur][!st.test(i)],res |= (1 << i);
else
cur = ch[cur][st.test(i)];
}
return res;
}
};
int d[100005];
vector<pii> e[100005];
void dfs(int u,int fa){
for(auto v:e[u]) {
if(v.fi == fa) continue;
d[v.fi] = d[u] ^ v.se;
dfs(v.fi,u);
}
}
Trie t;
int main(){
int n = rd();
for(int i = 0;i < n - 1;i++){
int x = rd();
int y = rd();
int w = rd();
e[x].push_back(make_pair(y,w));
e[y].push_back(make_pair(x,w));
}
dfs(1,0);
t.insert(d[1]);
int ans = -1;
for(int i = 2;i <= n;i++){
ans = max(ans,t.get(d[i]));
t.insert(d[i]);
}
cout << ans;
}