zoukankan      html  css  js  c++  java
  • hdu6191(树上启发式合并)

    hdu6191

    题意

    给你一棵带点权的树,每次查询 (u)(x) ,求以 (u) 为根结点的子树上的结点与 (x) 异或后最大的结果。

    分析

    看到子树,直接上树上启发式合并,看到异或,上 (Trie)
    这道题就是两个经典的题目结合了一波。

    树上启发式合并处理这种需要查询整个子树的题目尤其有用,可以复用大量的信息。
    离线查询后,到要查询的结点直接在 (Trie) (01) 树上跑一下即可。

    先去理解一波 树上启发式合并((dsu on tree)),就会发现这真是一道模板题

    code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MAXN = 1e5 + 100;
    const int MX = 30;
    struct Ex {
        int id, x;
    };
    struct Trie {
        int val[MAXN * 30], nxt[MAXN * 30][2], L, root;
        int newnode() {
            memset(nxt[L], -1, sizeof nxt[L]);
            return L++;
        }
        void init() {
            L = 0;
            root = newnode();
        }
        void update(int x, int key) {
            int now = root;
            for(int i = MX; i >= 0; i--) {
                int o = (x >> i) & 1;
                if(nxt[now][o] == -1) nxt[now][o] = newnode();
                now = nxt[now][o];
                val[now] += key;
            }
        }
        int query(int x) {
            int res = 0;
            int now = root;
            for(int i = MX; i >= 0; i--) {
                int o = (x >> i) & 1;
                if(val[nxt[now][!o]]) {
                    now = nxt[now][!o];
                    res |= (1 << i);
                } else {
                    now = nxt[now][o];
                }
            }
            return res;
        }
    }trie;
    vector<Ex> ex[MAXN];
    int fa[MAXN], son[MAXN], dep[MAXN], siz[MAXN];
    int col[MAXN];
    int cnt, head[MAXN];
    struct Edge {
        int to, next;
    }e[MAXN << 1];
    void addedge(int u, int v) {
        e[cnt].to = v;
        e[cnt].next = head[u];
        head[u] = cnt++;
    }
    void dfs(int u) {
        siz[u] = 1; son[u] = 0;
        for(int i = head[u]; ~i; i = e[i].next) {
            if(e[i].to != fa[u]) {
                fa[e[i].to] = u;
                dep[e[i].to] = dep[u] + 1;
                dfs(e[i].to);
                if(siz[e[i].to] > siz[son[u]]) son[u] = e[i].to;
                siz[u] += siz[e[i].to];
            }
        }
    }
    int n, q;
    int vis[MAXN];
    int ans[MAXN];
    void update(int u, int key) {
        trie.update(col[u], key);
        for(int i = head[u]; ~i; i = e[i].next) {
            if(e[i].to != fa[u] && !vis[e[i].to]) update(e[i].to, key);
        }
    }
    void dfs1(int u, int flg) {
        for(int i = head[u]; ~i; i = e[i].next) {
            if(e[i].to != fa[u] && e[i].to != son[u]) dfs1(e[i].to, 1);
        }
        if(son[u]) {
            dfs1(son[u], 0);
            vis[son[u]] = 1;
        }
        update(u, 1);
        for(int i = 0; i < ex[u].size(); i++) {
            ans[ex[u][i].id] = trie.query(ex[u][i].x);
        }
        if(son[u]) vis[son[u]] = 0;
        if(flg) {
            update(u, -1);
        }
    }
    
    int main() {
        while(~scanf("%d%d", &n, &q)) {
            for(int i = 1; i <= n; i++) {
                ex[i].clear();
                fa[i] = son[i] = dep[i] = siz[i] = 0;
            }
            memset(vis, 0, sizeof vis);
            memset(ans, 0, sizeof ans);
            trie.init();
            cnt = 0;
            memset(head, -1, sizeof head);
            for(int i = 1; i <= n; i++) {
                scanf("%d", &col[i]);
            }
            for(int i = 2; i <= n; i++) {
                int u;
                scanf("%d", &u);
                addedge(u, i);
                addedge(i, u);
            }
            for(int i = 0; i < q; i++) {
                int u, x;
                scanf("%d%d", &u, &x);
                ex[u].push_back(Ex{i, x});
            }
            dfs(1);
            dfs1(1, -1);
            for(int i = 0; i < q; i++) {
                printf("%d
    ", ans[i]);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    20191003 尚硅谷Spring Cloud教学视频
    20190928 On Java8 第二十三章 注解
    C# 输出结果有System.Byte[]
    linux 命令
    用go run命令启动main package中的多个文件
    Docker使用入门
    Go实现mqtt服务
    MongoDB的Go语言驱动注意点
    Go实现发送解析GET与POST请求
    用Go实现RabbitMQ消息收发
  • 原文地址:https://www.cnblogs.com/ftae/p/7459839.html
Copyright © 2011-2022 走看看