• POJ 3764 (异或+字典树)


    早就听过用字典树求异或最大值,然而没做过。发现一碰到异或的题就GG,而且因为以前做过的一道类似的题(事实上并不类似)限制了思路,蠢啊= =。

    题意:一棵带权的树,求任意两点间路径异或的最大值。

    题解:设xor(a,b)是求a,b间路径的异或值,那么xor(a,b)=xor(root,a)^xor(root,b)。因为如果LCA(a,b)==root时结论显然成立,不然的话就会有重复走过的部分,但是异或有性质x^x=0,所以LCA(a,b)!=root结论依然成立。

    这样题目就很简单了。对每一个xor(root,i)(0<i<n)建立trie,因为每个数转成二进制都是一个01组成的字符串,用来建立trie。然后对每一个xor(root,i)在trie查询最大值就好了。

    #include <vector>
    #include <list>
    #include <map>
    #include <set>
    #include <queue>
    #include <stack>
    #include <bitset>
    #include <algorithm>
    #include <numeric>
    #include <utility>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    #include <cstdio>
    #include <cmath>
    #include <cstdlib>
    #include <cstring>
    #define pk printf("lalala");
    #define ppp(x) printf("%d
    ", x)
    using namespace std;
    #define PI acos(-1.0)
    #define EXP exp(1.0)
    #define EPS 1E-6
    #define clr(x,c) memset(x,c,sizeof(x))
    
    
    const int KIND = 2;
    const int MAXN = 5000005;
    const int N = 100005;
    int cnt_node;
    
    struct node{
        node* nt[KIND];
        void init(){
            memset(nt, 0, sizeof(nt));
        }
    } Heap[MAXN];
    node *root;
    int Xor[N];
    
    inline node* new_node()
    {
        Heap[cnt_node].init();
        return &Heap[cnt_node++];
    }
    
    void insert(node* root, int *str)
    {
        for(int i = 0; i <= 30; ++i){
            int ch = str[i];
            if(root->nt[ch] == NULL)
                root->nt[ch] = new_node();
            root = root->nt[ch];
        }
    }
    
    int count(node* root, int *str)
    {
        int ans = 0;
        for(int i = 0; i <= 30; ++i){
            int ch = str[i];
            int need = (ch ^ 1);
            if(root->nt[need] == NULL) {
                root = root->nt[ch];
            } else {
                root = root->nt[need];
                ans += (1 << (30 - i));
            }
        }
        return ans;
    }
    
    struct Edge {
        int to;
        int w;
        int next;
    } edge[N * 2];
    
    int cnt_edge;
    int head[N];
    
    void add_edge(int u, int v, int w)
    {
        edge[cnt_edge].to = v;
        edge[cnt_edge].w = w;
        edge[cnt_edge].next = head[u];
        head[u] = cnt_edge++;
    }
    
    void dfs(int u, int fa, int val)
    {
        Xor[u] = val;
        for (int i = head[u]; i != -1; i = edge[i].next) {
            int v = edge[i].to;
            int w = edge[i].w;
            if (v == fa) continue;
            dfs(v, u, val^w);
        }
    }
    
    
    int str[N][40];
    
    int main()
    {
        int n;
        while (~scanf("%d",&n)) {
            clr(head, -1);
            cnt_edge = 0;
            cnt_node = 0;
            root = new_node();
            int u, v, w;
            for (int i = 1; i < n; ++i) {
                scanf("%d%d%d",&u, &v, &w);
                add_edge(u, v, w);
                add_edge(v, u, w);
            }
            dfs(0, -1, 0);
            //for (int i = 0; i < n; ++i) printf("%d ", Xor[i]); printf("
    ");
            int ans = 0;
            for (int i = 0; i < n; ++i) {
                int idx = 0;
                for (int b = 30; b >= 0; --b) {
                    str[i][idx++] = Xor[i] & (1 << b) ? 1 : 0;
                }
                //for (int j = 0; j < idx; ++j) printf("%d ", str[i][j]); printf("
    ");
                insert(root, str[i]);
            }
            for (int i = 0; i < n; ++i) {
                ans = max(ans, count(root, str[i]));
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    .net证书Rsa加密
    $.ajax
    EF通用CRED
    JSON.pase()
    mysql 使用EF6.0CodeFirst
    jenkins 自动构建——shell脚本
    nginx配置示例
    easyui 随笔
    javascript 随笔
    asp.net mvc4 过滤器的简单应用:登录验证
  • 原文地址:https://www.cnblogs.com/wenruo/p/5502304.html
Copyright © 2020-2023  润新知