zoukankan      html  css  js  c++  java
  • 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;
    }
    
    
  • 相关阅读:
    一个好的时间函数
    Codeforces 785E. Anton and Permutation
    Codeforces 785 D. Anton and School
    Codeforces 510 E. Fox And Dinner
    Codeforces 242 E. XOR on Segment
    Codeforces 629 E. Famil Door and Roads
    Codeforces 600E. Lomsat gelral(Dsu on tree学习)
    Codeforces 438D The Child and Sequence
    Codeforces 729E Subordinates
    【ATcoder】D
  • 原文地址:https://www.cnblogs.com/hznumqf/p/14540307.html
Copyright © 2011-2022 走看看