zoukankan      html  css  js  c++  java
  • HDU

    题意:

      给出一个带点权的树。q次询问,每次询问给出u和x,求点u的子树中与x异或的最大值。

    题解:

      将询问离线化。

      每颗节点动态建立字典树。每个节点和自己的孩子合并,但是这样会改变子树节点的字典树,所以就在每个节点回溯的时候计算出该节点的答案。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    using namespace std;
    typedef long long ll;
    const int N = 1e5+5;
    int n, q;
    int tot, num, f;
    int w[N];
    int root[N];
    int head[N], to[N], nxt[N];
    int tre[N*40][2];
    int u, x;
    vector<int> g[N];
    vector<int> id[N];
    int ans[N];
    void build(int id) {
        scanf("%d", &w[id]);
        root[id] = ++tot;
        int c = tot;
        for(int i = 30; i >= 0; i--) {
            if(w[id]&(1<<i)) tre[c][1] = ++tot;
            else tre[c][0] = ++tot;
            c = tot;
        }
    }
    void update(int u, int v) {
        if(tre[v][0]>0) {
            if(tre[u][0]==0) tre[u][0] = tre[v][0];
            else update(tre[u][0], tre[v][0]);
        }
        if(tre[v][1]>0) {
            if(tre[u][1]==0) tre[u][1] = tre[v][1];
            else update(tre[u][1], tre[v][1]);
        }
    }
    int query(int u, int x) {
        int res = 0;
        int c = root[u];
        for(int i = 30; i >= 0; i--) {
            int p = (x>>i)&1;
            if(tre[c][p^1] > 0) res |= (1<<i), c = tre[c][p^1];
            else if(tre[c][p] > 0) c = tre[c][p];
        }
        return res;
    }
    void dfs(int u) {
        for(int i = head[u]; ~i; i = nxt[i]) {
            dfs(to[i]);
            update(root[u], root[to[i]]);
        }
        int len = g[u].size();
        for(int i = 0; i < len; i++) ans[id[u][i]] = query(u, g[u][i]);
    }
    int main() {
        while(~scanf("%d%d", &n, &q)) {
            tot = num = 0;
            memset(tre, 0, sizeof(tre));
            memset(head, -1, sizeof(head));
            for(int i = 1; i <= n; i++) {
                g[i].clear();
                id[i].clear();
            }
            for(int i = 1; i <= n; i++) build(i);
            for(int i = 2; i <= n; i++) {
                scanf("%d", &f);
                to[++num] = i; nxt[num] = head[f]; head[f] = num;
            }
            for(int i = 1; i <= q; i++) {
                scanf("%d%d", &u, &x);
                g[u].push_back(x);
                id[u].push_back(i);
            }
            dfs(1);
            for(int i = 1; i <= q; i++) printf("%d
    ", ans[i]);
        }
    }
    View Code
  • 相关阅读:
    Linux Shell入门
    Linux系统结构
    Ubuntu bond 配置
    VXLAN概述
    lsof
    入驻博客园,希望可以跟大家一起讨论,一起学习和进步。
    版本管理工具小乌龟TortoiseGit的安装和使用(2)
    版本管理工具小乌龟TortoiseGit的安装和使用(1)
    定义变量时未初始化赋值的问题
    BlackBerry 9900刷机
  • 原文地址:https://www.cnblogs.com/Pneuis/p/9152968.html
Copyright © 2011-2022 走看看