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
  • 相关阅读:
    jxl切割excel文件
    Oracle 11g新增not null的字段比10g快--新特性
    再按一次退出程序
    项目进阶 之 集群环境搭建(一)概述
    分布式搜索elasticsearch 环境搭建
    WikiCFP--A Wiki for Calls For Papers
    Java的结构之美【2】——销毁对象
    Java的结构之美【1】——构造对象
    Bottle 中文文档
    我的算法学习之路
  • 原文地址:https://www.cnblogs.com/oyking/p/3336984.html
Copyright © 2011-2022 走看看