• 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
  • 相关阅读:
    接口
    echartsx轴名称过长,截断+鼠标划过显示全称
    浏览器兼容的几点思路
    安装gulp教程(整理)
    TortoiseSVN文件夹及文件图标、标识、绿色小对号不显示解决方法(转载)
    css实现小三角(转载+个人笔记)
    css常用样式(待更新)
    表格样式设计和几点考量
    一些大神或者觉得有益的博客、专栏等(不定时更新)
    搭配bootstracp运用的通用样式(想起来就开个头,待补充……)
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/9557265.html
Copyright © 2020-2023  润新知