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
  • 相关阅读:
    php打印出10*10表格
    php打印出1到2000年之间所有的闰年
    借鉴一篇好文章
    女程序员的预备篇
    SQL存储过程删除数据库日志文件的方法
    Mongodb无法访问28107的问题
    使用 xsd.exe 命令工具将 xsd 架构生成 类(CS) 文件
    C# 用POST提交json数据
    WinForm 使用 HttpUtility
    Sql Server 分区之后增加新的分区
  • 原文地址:https://www.cnblogs.com/oyking/p/3336984.html
Copyright © 2011-2022 走看看