zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    Java多线程系列 基础篇10 wait/notify/sleep/yield/join
    Java多线程系列 基础篇09 Object.wait/notifyJVM源码实现
    Java多线程系列 基础篇07 synchronized底层优化
    Java多线程系列 基础篇06 synchronized(同步锁)
    Java多线程系列 基础篇05 synchronized关键字
    Java多线程系列 基础篇04 线程中断
    Java多线程系列 基础篇03 线程的优先级和守护线程
    Java多线程系列 基础篇02 线程的创建和运行
    MySQL进阶14--标识列(自增序列/auto_increment)--设置/展示步长--设置/删除标示列
    MySQL进阶13--常见六大约束: 非空/默认/主键/唯一约束/检查约束/外键约束--表级约束 / 列级约束
  • 原文地址:https://www.cnblogs.com/oyking/p/3336984.html
Copyright © 2011-2022 走看看