zoukankan      html  css  js  c++  java
  • hdu 4757 Tree(可持久化字典树)

    题目链接:hdu 4757 Tree

    题目大意:给定一棵树,每一个节点有一个值。如今有Q次询问,每次询问u到v路径上节点值与w亦或值的最大值。

    解题思路:刚開始以为是树链剖分,事实上树链剖分仅仅是用来求LCA(能够不用树链剖分)。

    可持久化字典树。在每次插入的同一时候,不改动原先的节点。而是对全部改动的节点复制一个新的节点,而且在新的节点

    上做操作,这样做的目的是可以获取某次改动前的状态。同过可持久化的操作,保留了改动前后的公共数据。


    对给定树上的全部节点权值建立01字典树,然后每一个节点都保存着一棵可持久化字典树。表示的是从根节点到该节点路

    径节点所形成的字典树。对每一个节点建树的过程通过改动其父亲节点而得到。

    查询时,对依据u。v。lca(u,v)三棵字典树的情况确定亦或的最大值,注意lca(u,v)这个节点要单独计算。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 1e5 + 5;
    
    int N, Q, E, V[maxn], first[maxn], jump[maxn * 2], link[maxn * 2];
    int id, idx[maxn], top[maxn], far[maxn], son[maxn], dep[maxn], cnt[maxn];
    
    inline void add_Edge (int u, int v) {
        link[E] = v;
        jump[E] = first[u];
        first[u] = E++;
    }
    
    inline void dfs (int u, int pre, int d) {
        far[u] = pre;
        son[u] = 0;
        dep[u] = d;
        cnt[u] = 1;
    
        for (int i = first[u]; i + 1; i = jump[i]) {
            int v = link[i];
            if (v == pre) 
                continue;
            dfs(v, u, d + 1);
            cnt[u] += cnt[v];
            if (cnt[son[u]] < cnt[v])
                son[u] = v;
        }
    }
    
    inline void dfs (int u, int rot) {
        idx[u] = ++id;
        top[u] = rot;
    
        if(son[u])
            dfs(son[u], rot);
    
        for (int i = first[u]; i + 1; i = jump[i]) {
            int v = link[i];
            if (v == far[u] || v == son[u]) 
                continue;
            dfs(v, v);
        }
    }
    
    inline int LCA (int u, int v) {
        int p = top[u], q = top[v];
        while (p != q) {
            if (dep[p] < dep[q]) {
                swap(p, q);
                swap(u, v);
            }
    
            u = far[p];
            p = top[u];
        }
        return dep[u] > dep[v] ?

    v : u; } void init() { E = id = 0; memset(first, -1, sizeof(first)); for (int i = 1; i <= N; i++) scanf("%d", &V[i]); int u, v; for (int i = 1; i < N; i++) { scanf("%d%d", &u, &v); add_Edge(u, v); add_Edge(v, u); } dfs(1, 0, 0); dfs(1, 1); } struct node { int g[2], c; }nd[maxn * 20]; int sz, root[maxn]; int insert (int r, int w) { int ret, x; ret = x = sz++; nd[x] = nd[r]; for (int i = 15; i >= 0; i--) { int v = (w>>i)&1; int t = sz++; nd[t] = nd[nd[x].g[v]]; nd[t].c++; nd[x].g[v] = t; x = t; } return ret; } void dfs(int u) { root[u] = insert(root[far[u]], V[u]); for (int i = first[u]; i + 1; i = jump[i]) { int v = link[i]; if (v == far[u]) continue; dfs(v); } } void Tire_init() { sz = 1; root[0] = nd[0].c = 0; memset(nd[0].g, 0, sizeof(nd[0].g)); dfs(1); } int query(int x, int y, int z, int w) { int ans = V[z] ^ w, ret = 0; z = root[z]; for (int i = 15; i >= 0; i--) { int v = ((w>>i)&1) ^ 1; int cnt = nd[nd[x].g[v]].c + nd[nd[y].g[v]].c - 2 * nd[nd[z].g[v]].c; if (cnt) ret |= (1<<i); else v = v^1; x = nd[x].g[v], y = nd[y].g[v], z = nd[z].g[v]; } return max(ans, ret); } int main () { while (scanf("%d%d", &N, &Q) == 2) { init(); Tire_init(); int u, v, w; while (Q--) { scanf("%d%d%d", &u, &v, &w); printf("%d ", query(root[u], root[v], LCA(u, v), w)); } } return 0; }

  • 相关阅读:
    Python学习之路 (五)爬虫(四)正则表示式爬去名言网
    Python学习之路 (四)爬虫(三)HTTP和HTTPS
    Python学习之路 (三)爬虫(二)
    Python学习之路 (二)爬虫(一)
    Python学习之路 (一)开发环境搭建
    ZooKeeper学习之路 (十一)ZooKeeper API的应用
    ZooKeeper学习之路 (十)Hadoop的HA集群的机架感知
    Spring Security
    Spring Validation
    [转]linux下完全备份数据库mysql
  • 原文地址:https://www.cnblogs.com/slgkaifa/p/6782821.html
Copyright © 2011-2022 走看看