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;
    }
    
    
  • 相关阅读:
    JavaScript 类型转换
    Bjarne Stroustrup
    格拉丘纳斯的上下级关系理论
    成功者必须具备的三大技能
    ASP.NET/Perl.NET (转)
    iPhone/Mac ObjectiveC内存管理教程和原理剖析
    objectivec日期之间比较可用以下方法
    Centos下安装中文输入法
    C#中数字的四舍五入与只取整
    关于Application.Lock和Lock(obj)
  • 原文地址:https://www.cnblogs.com/hznumqf/p/14540307.html
Copyright © 2011-2022 走看看