博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 4757 Tree 可持久化字典树
阅读量:7288 次
发布时间:2019-06-30

本文共 4705 字,大约阅读时间需要 15 分钟。

Tree

Time Limit: 20 Sec

Memory Limit: 256 MB

题目连接

http://acm.hdu.edu.cn/showproblem.php?pid=4757

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.

Sample Input

3 2

1 2 2
1 2
2 3
1 3 1
2 3 2

Sample Output

3

0

HINT

 

题意

给你一棵树,每个点有一个权值

Q次询问,每次询问你在(x,y)这条链上的点与c异或的最大值是多少

题解:

可持久化字典树,对于每个点都保存一棵可持久化字典树

每个字典树先从他的fa那儿复制过来,然后再将自己的这个字符串插入进去就好了

可持久化字典树模板:http://www.cnblogs.com/qscqesze/p/5032334.html

代码:

#include
#include
#include
#include
using namespace std;#define maxn 100005int w[maxn],n,q;vector
E[maxn];int root[maxn];// 使用前调用初始化函数 init() 同时 root[0] = 0;struct Trie_Persistent{ const static int LetterSize = 5; // 字符集大小 const static int TrieSize = 20 * ( 1e5 + 50); // 可能的所有节点总数量 int tot; // 节点总数 //节点类型 struct node { int ptr[LetterSize]; // trie_node_ptr[] int cnt[LetterSize]; // 维护字符集数目 }tree[TrieSize]; // 获取字符集哈希编号 , 必须在 [0 , LetterSize) 之内 inline int GetLetterIdx(int c){
return c - 'a';} // 插入字符串 str , 上一个副本是 f /* int insert(const char * str ,int f){ int len = strlen( str ); int res = tot++; // 建立虚拟根结点 tree[res] = tree[f]; // 初始化 int cur = res; // 当前指针 for(int i = 0 ; i < len ; ++ i){ int idx = GetLetterIdx( str[i] ); // 获取字符编号 int p = tot ++ ; // 创建下一个虚拟节点 tree[cur].cnt[idx] ++ ; tree[cur].ptr[idx] = p; f = tree[f].ptr[idx]; // 上一个副本的指针更新 tree[p] = tree[f]; // updata information; cur = tree[cur].ptr[idx]; // updata ptr } return res; } */ int insert(int t,int f){ int str[30]; for(int i = 15 ; i >= 0 ; -- i){ if ( t >> i & 1) str[15 - i] = 1; else str[15 - i] = 0; } int res = tot++; // 建立虚拟根结点 tree[res] = tree[f]; // 初始化 int cur = res; // 当前指针 for(int i=0;i<16;i++) { int idx = str[i] ; // 获取字符编号 int p = tot ++ ; // 创建下一个虚拟节点 tree[cur].cnt[idx] ++ ; tree[cur].ptr[idx] = p; f = tree[f].ptr[idx]; // 上一个副本的指针更新 tree[p] = tree[f]; // updata information; cur = tree[cur].ptr[idx]; // updata ptr } return res; } // 在 [l ,r] 副本中查找字符串str // 参数带入( str , root[l-1] , root[r]) int find(int t , int l ,int r){ int str[30]; for(int i = 15 ; i >= 0 ; -- i){ if ( t >> i & 1) str[15 - i] = 1; else str[15 - i] = 0; } int ans = 0; for(int i = 0 ; i < 16 ; ++ i){ int idx = str[i]^1 ; // 获取字符Hash int cnt = tree[r].cnt[idx] - tree[l].cnt[idx]; if(!cnt) idx = idx^1; else ans|=(1<<(15-i)); l = tree[l].ptr[idx]; r = tree[r].ptr[idx]; } return ans; } void init(){tot = 1;for(int i = 0 ; i < LetterSize ; ++ i) tree[0].ptr[i] = 0 , tree[0].cnt[i] = 0; } // 虚拟节点}trie;int lca[maxn][24];int deep[maxn];void init(int n){ trie.init(); root[0]=0; for(int i=0;i<=n;i++) { E[i].clear(); w[i]=0; root[i]=0; } for(int i = 1 ; i <= n ; ++ i) for(int j = 0 ; j <= 20 ; ++ j) lca[i][j] = 0;}int querylca(int u ,int v){ if(deep[u] < deep[v]) swap( u , v ); for(int i = 20 ; i >= 0 ; --i) if(deep[u] - (1 << i) >= deep[v]) u = lca[u][i]; if( u == v ) return u; for(int i = 20 ; i >= 0 ; -- i) if(lca[u][i] != lca[v][i]) u = lca[u][i] , v = lca[v][i]; return lca[u][0];}void build(int x,int fa){ root[x]=trie.insert(w[x],root[fa]); for(int i=0;i

 

你可能感兴趣的文章
关于visual assist x插件不能用的解决方案
查看>>
Linux iptables:规则组成
查看>>
HDU 4442 Physical Examination【水题】【思维题】
查看>>
NET 命令 常用方法!
查看>>
我的友情链接
查看>>
memcached
查看>>
谁搞死了你的软件?
查看>>
Promise 对象
查看>>
Windows快速添加IP地址
查看>>
AS3.0 事件流
查看>>
“将截断字符串或二进制数据。语句已终止……”问题的解决
查看>>
红苹果IP代理软件 v6.2
查看>>
Centos5.x & Centos6.x 使用mail命令发邮件以及如何伪造发件人
查看>>
JavaScript系列:ECMAScript原始类型
查看>>
centos反编译APK包
查看>>
CSS系列:CSS中盒子的浮动与定位
查看>>
windows 用户用户组迁移
查看>>
Linux系统扩充2
查看>>
linux新手的心得
查看>>
我的友情链接
查看>>