• HDU 4757 Tree(可持久化字典树)(2013 ACM/ICPC Asia Regional Nanjing Online)


    Problem Description
      Zero and One are good friends who always have fun with each other. This time, they decide to do something on a tree which is a kind of graph that there is only one path from node to node. First, Zero will give One an tree and every node in this tree has a value. Then, Zero will ask One a series of queries. Each query contains three parameters: x, y, z which mean that he want to know the maximum value produced by z xor each value on the path from node x to node y (include node x, node y). Unfortunately, One has no idea in this question. So he need you to solve it.
     
    Input
      There are several test cases and the cases end with EOF. For each case:

      The first line contains two integers n(1<=n<=10^5) and m(1<=m<=10^5), which are the amount of tree’s nodes and queries, respectively.

      The second line contains n integers a[1..n] and a[i](0<=a[i]<2^{16}) is the value on the ith node.

      The next n–1 lines contains two integers u v, which means there is an connection between u and v.

      The next m lines contains three integers x y z, which are the parameters of Zero’s query.
     
    Output
      For each query, output the answer.
     
    题目大意:给你一颗n个点的树,每个点有一个权值。然后有m个询问,问从x到y的简单路径中,权值 xor z最大是多少。
    思路:可持久化的0-1字典树,每个点在父节点的历史版本上新建一棵字典树,字典树上的每个结点给一个值记录从这个结点到树的根节点,有多少个权值会经过这个字典树上的结点。询问的时候在字典树上奏即可。由于a[i]<2^16,那么字典树的深度最大为16,空间复杂度为O(16 * n)。
    PS:tarjan果然要比RMQ快啊。
    PS2:数据保障z<2^16,虽然题目没讲……
     
    代码(1265MS):
      1 #include <cstdio>
      2 #include <iostream>
      3 #include <algorithm>
      4 #include <cstring>
      5 using namespace std;
      6 
      7 const int MAX = 100010;
      8 const int MAXN = 2 * MAX;
      9 const int MAXE = 2 * MAXN;
     10 
     11 int head[MAXN], weight[MAXN], fa[MAX];
     12 bool vis[MAX];
     13 int to[MAXE], next[MAXE], id[MAXE];
     14 int n, m, ecnt;
     15 
     16 inline void init() {
     17     memset(head, 0, sizeof(head));
     18     memset(vis, 0, sizeof(vis));
     19     for(int i = 1; i <= n; ++i) fa[i] = i;
     20     ecnt = 2;
     21 }
     22 
     23 inline void add_edge(int u, int v, int i) {
     24     to[ecnt] = v; id[ecnt] = i; next[ecnt] = head[u]; head[u] = ecnt++;
     25     to[ecnt] = u; id[ecnt] = i; next[ecnt] = head[v]; head[v] = ecnt++;
     26 }
     27 
     28 struct QUERY {
     29     int x, y, lca, z;
     30     void read(int i) {
     31         scanf("%d%d%d", &x, &y, &z);
     32         add_edge(x + n, y + n, i);
     33     }
     34 } Query[MAX];
     35 
     36 int get_set(int x) {
     37     return fa[x] == x ? x : fa[x] = get_set(fa[x]);
     38 }
     39 
     40 void dfs_LCA(int u, int f) {
     41     for(int p = head[u]; p; p = next[p]) {
     42         int &v = to[p];
     43         if(v == f) continue;
     44         dfs_LCA(v, u);
     45         fa[v] = u;
     46     }
     47     vis[u] = true;
     48     for(int p = head[u + n]; p; p = next[p]) {
     49         int v = to[p] - n;
     50         if(vis[v]) Query[id[p]].lca = get_set(v);
     51     }
     52 }
     53 
     54 struct Node {
     55     int go[2], cnt;
     56 } tree[20 * MAX];
     57 int root[MAX], Tcnt;
     58 
     59 void init_tree() {
     60     Tcnt = 1; root[0] = 0;
     61 }
     62 
     63 int insert(int x, int val) {
     64     tree[Tcnt] = tree[x];
     65     int ret = x = Tcnt++;
     66     for(int i = 15; i >= 0; --i) {
     67         int idx = (val >> i) & 1, t = Tcnt++;
     68         tree[t] = tree[tree[x].go[idx]];
     69         ++tree[t].cnt;
     70         tree[x].go[idx] = t;
     71         x = t;
     72     }
     73     return ret;
     74 }
     75 
     76 void dfs_build(int u, int f) {
     77     root[u] = insert(root[f], weight[u]);
     78     for(int p = head[u]; p; p = next[p]) {
     79         int &v = to[p];
     80         if(v == f) continue;
     81         dfs_build(v, u);
     82     }
     83 }
     84 
     85 int query(int x, int y, int lca, int val) {
     86     int ret = 0, ret_lca = weight[lca] ^ val;
     87     x = root[x], y = root[y], lca = root[lca];
     88     for(int i = 15; i >= 0; --i) {
     89         int idx = !((val >> i) & 1);
     90         int cnt = tree[tree[x].go[idx]].cnt + tree[tree[y].go[idx]].cnt - 2 * tree[tree[lca].go[idx]].cnt;
     91         if(cnt > 0) ret |= (1 << i);
     92         else idx = !idx;
     93         x = tree[x].go[idx], y = tree[y].go[idx], lca = tree[lca].go[idx];
     94     }
     95     return max(ret, ret_lca);
     96 }
     97 
     98 int main() {
     99     while(scanf("%d%d", &n, &m) != EOF) {
    100         for(int i = 1; i <= n; ++i) scanf("%d", &weight[i]);
    101         init();
    102         for(int i = 1; i < n; ++i) {
    103             int u, v;
    104             scanf("%d%d", &u, &v);
    105             add_edge(u, v, 0);
    106         }
    107         for(int i = 1; i <= m; ++i) Query[i].read(i);
    108         dfs_LCA(1, 0);
    109         init_tree();
    110         dfs_build(1, 0);
    111         for(int i = 1; i <= m; ++i)
    112             printf("%d
    ", query(Query[i].x, Query[i].y, Query[i].lca, Query[i].z));
    113     }
    114 }
    View Code
  • 相关阅读:
    【干货】Windows系统信息收集篇
    【干货】SIFT-Workstation 下载与安装 不跳过每一个细节部分
    【干货】从没有数据结构的二进制中(内存或者未隐藏的数据块)提取关键信息
    【干货】操纵时间 感受威胁 MAC time时间戳视角
    【干货】证据被毁?数据恢复出来
    【干货】已Window7 系统为例,谈谈boot引导程序-------附带看看数据隐藏
    IDEA创建各种不同的工程的方法
    IDEA全局配置
    IDEA项目添加第三方依赖
    IDEA打开最近打开的项目以及关闭项目
  • 原文地址:https://www.cnblogs.com/oyking/p/3336984.html
Copyright © 2020-2023  润新知