zoukankan      html  css  js  c++  java
  • HDU 6191 Query on A Tree ( 2017广西邀请赛 && 可持久化Trie )

    题目链接

    题意 : 给你一棵树、树上的每个点都有点权、之后有若干次问询、每次问询给出一个节点编号以及一个整数 X 、问你以给出节点为根的子树中哪个节点和 X 异或最大、输出这个值

    分析 :

    看到这种树上异或最值的问题

    可以考虑使用 Trie 来解决

    首先涉及到子树

    我们可以利用 DFS 序来构造出每个根的子树

    DFS 序有很好的性质、其子树的所有节点必定是序列中连续的一段

    那么我们就可以对这个 DFS 序列建立可持久化 Trie

    然后通过类似前缀和减法的方式得到问询节点子树表示的区间中

    所有数组成的 Trie 、然后通过贪心的方法来得到最大异或值

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5 + 10;
    const int maxNode = (maxn<<5);
    int root[maxn];
    int sz[maxNode];
    int ch[maxNode][2];
    int totNode = 0;
    
    int newNode()
    {
        totNode++;
        memset(ch[totNode], 0, sizeof(ch[totNode]));
        sz[totNode] = 0;
        return totNode;
    }
    
    inline void Insert(int F, int C, int val)
    {
        F = root[F], C = root[C];
        for(int i=30; i>=0; i--){
            int bit = (val>>i) & 1;
            if(!ch[C][bit]){
                ch[C][bit] = newNode();
                ch[C][!bit] = ch[F][!bit];
                sz[ ch[C][bit] ] = sz[ ch[F][bit] ];
            }
            C = ch[C][bit], F = ch[F][bit];
            sz[C]++;
        }
    }
    
    int Query(int x, int y, int val)
    {
        int ret = 0;
        for(int i=30; i>=0; i--){
            int c = (val>>i) & 1;
            if(sz[ch[y][!c]] - sz[ch[x][!c]] > 0)
                ret += (1<<i),
                y = ch[y][!c],
                x = ch[x][!c];
            else x = ch[x][c], y = ch[y][c];
        }
        return ret;
    }
    
    struct EDGE{ int v, w, nxt; }Edge[maxn];
    int Head[maxn], EdgeCnt = 0;
    int weight[maxn];
    
    inline void Edge_init(int n)
    {
        memset(sz, 0, sizeof(sz));
        memset(ch, 0, sizeof(ch));
        memset(Head, -1, sizeof(Head));
        EdgeCnt = 0;
    }
    
    inline void AddEdge(int From, int To, int Weight)
    {
        Edge[EdgeCnt].v = To;
        Edge[EdgeCnt].w = Weight;
        Edge[EdgeCnt].nxt = Head[From];
        Head[From] = EdgeCnt++;
    }
    
    int squ[maxn], squLen = 1;
    int st[maxn], en[maxn];
    void DFS(int v)
    {
        st[v] = squLen;
        squ[squLen++] = v;
        for(int i=Head[v]; i!=-1; i=Edge[i].nxt){
            int Eiv = Edge[i].v;
            DFS(Eiv);
        }
        en[v] = squLen-1;
    }
    
    
    int main(void)
    {
    
        int n, q;
        while(~scanf("%d %d", &n, &q)){
    
            squLen = 1;
            totNode = 0;
            Edge_init(n);
    
            for(int i=1; i<=n; i++) scanf("%d", &weight[i]);
            for(int i=1; i<=n-1; i++){
                int Fa; scanf("%d", &Fa);
                AddEdge(Fa, i+1, weight[i]);
            }
    
            DFS(1);
    
            root[0] = ch[0][0] = ch[0][1] = 0;
            for(int i=1; i<squLen; i++) root[i] = newNode();
            for(int i=1; i<squLen; i++)
                Insert(i-1, i, weight[squ[i]]);
    
            while(q--){
                int v, x;
                scanf("%d %d", &v, &x);
                printf("%d
    ", Query(st[v]-1, en[v], x));
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    将PHP文件生成静态文件源码
    Entity Framework Code First 学习日记(6)一对多关系
    Entity Framework Code First 学习日记(5)
    Entity Framework Code First 学习日记(3)
    Entity Framework Code First 学习日记(7)多对多关系
    Entity Framework Code First学习日记(2)
    Entity Framework Code First 学习日记(8)一对一关系
    Entity Framework Code First 学习日记(9)映射继承关系
    Entity Framework Code First 学习日记(10)兼容遗留数据库
    Entity Framework Code First 学习日记(4)
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/9557265.html
Copyright © 2011-2022 走看看