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;
}

原文地址:https://www.cnblogs.com/hznumqf/p/14540307.html