hdu 4757 Tree(可持久化字典树)
来源:互联网 发布:火麒麟红包软件 编辑:程序博客网 时间:2024/05/21 17:13
题目链接:hdu 4757 Tree
题目大意:给定一棵树,每个节点有一个值,现在有Q次询问,每次询问u到v路径上节点值与w亦或值的最大值。
解题思路:刚开始以为是树链剖分,其实树链剖分只是用来求LCA(可以不用树链剖分)。
可持久化字典树,在每次插入的同时,不修改原先的节点,而是对所有修改的节点复制一个新的节点,并且在新的节点
上做操作,这样做的目的是能够获取某次修改前的状态。同过可持久化的操作,保留了修改前后的公共数据。
对给定树上的所有节点权值建立01字典树,然后每个节点都保存着一棵可持久化字典树,表示的是从根节点到该节点路
径节点所形成的字典树。对每个节点建树的过程通过修改其父亲节点而得到。
查询时,对根据u,v,lca(u,v)三棵字典树的情况确定亦或的最大值,注意lca(u,v)这个节点要单独计算。
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 1e5 + 5;int N, Q, E, V[maxn], first[maxn], jump[maxn * 2], link[maxn * 2];int id, idx[maxn], top[maxn], far[maxn], son[maxn], dep[maxn], cnt[maxn];inline void add_Edge (int u, int v) { link[E] = v; jump[E] = first[u]; first[u] = E++;}inline void dfs (int u, int pre, int d) { far[u] = pre; son[u] = 0; dep[u] = d; cnt[u] = 1; for (int i = first[u]; i + 1; i = jump[i]) { int v = link[i]; if (v == pre) continue; dfs(v, u, d + 1); cnt[u] += cnt[v]; if (cnt[son[u]] < cnt[v]) son[u] = v; }}inline void dfs (int u, int rot) { idx[u] = ++id; top[u] = rot; if(son[u]) dfs(son[u], rot); for (int i = first[u]; i + 1; i = jump[i]) { int v = link[i]; if (v == far[u] || v == son[u]) continue; dfs(v, v); }}inline int LCA (int u, int v) { int p = top[u], q = top[v]; while (p != q) { if (dep[p] < dep[q]) { swap(p, q); swap(u, v); } u = far[p]; p = top[u]; } return dep[u] > dep[v] ? v : u;}void init() { E = id = 0; memset(first, -1, sizeof(first)); for (int i = 1; i <= N; i++) scanf("%d", &V[i]); int u, v; for (int i = 1; i < N; i++) { scanf("%d%d", &u, &v); add_Edge(u, v); add_Edge(v, u); } dfs(1, 0, 0); dfs(1, 1);}struct node { int g[2], c;}nd[maxn * 20];int sz, root[maxn];int insert (int r, int w) { int ret, x; ret = x = sz++; nd[x] = nd[r]; for (int i = 15; i >= 0; i--) { int v = (w>>i)&1; int t = sz++; nd[t] = nd[nd[x].g[v]]; nd[t].c++; nd[x].g[v] = t; x = t; } return ret;}void dfs(int u) { root[u] = insert(root[far[u]], V[u]); for (int i = first[u]; i + 1; i = jump[i]) { int v = link[i]; if (v == far[u]) continue; dfs(v); }}void Tire_init() { sz = 1; root[0] = nd[0].c = 0; memset(nd[0].g, 0, sizeof(nd[0].g)); dfs(1);}int query(int x, int y, int z, int w) { int ans = V[z] ^ w, ret = 0; z = root[z]; for (int i = 15; i >= 0; i--) { int v = ((w>>i)&1) ^ 1; int cnt = nd[nd[x].g[v]].c + nd[nd[y].g[v]].c - 2 * nd[nd[z].g[v]].c; if (cnt) ret |= (1<<i); else v = v^1; x = nd[x].g[v], y = nd[y].g[v], z = nd[z].g[v]; } return max(ans, ret);}int main () { while (scanf("%d%d", &N, &Q) == 2) { init(); Tire_init(); int u, v, w; while (Q--) { scanf("%d%d%d", &u, &v, &w); printf("%d\n", query(root[u], root[v], LCA(u, v), w)); } } return 0;}
1 0
- hdu 4757 Tree(可持久化字典树)
- hdu-4757-Tree-树链剖分+可持久化字典树
- Hdu-4757 Tree(可持久化字典树)
- hdu 4757 Tree(可持久化字典树)
- HDU 4757 可持久化字典树(Trie)
- HDU 4757 树链剖分+可持久化字典树
- 2017 icpc广西邀请赛 K.Query on A Tree (hdu 6191)可持久化字典树
- HDU 6191 Query on A Tree [可持久化字典树]
- HDU 6191 Query on A Tree ( DFS序 + 可持久化字典树 )
- hdu 4757 Tree(可持久化Trie)
- hdu 6191 Query on A Tree(字典树启发式合并(动态建树) 可持久化字典树+dfs序)
- HDU 6191 DFS序+可持久化字典树
- 可持久化字典树
- HDU 6191 2017广西邀请赛Query on A Tree:可持久化01字典树(区间抑或最大值查询)
- HDU 4757 Tree 可持久化trie+lca
- HDU 3333 Turing Tree 可持久化线段树
- HDU 4757 Tree (倍增算法求LCA + 可持久化Trie树)
- HDU 4757 可持久化trie树
- JSP自建标签_1_TLD文件描述
- Android 实现能够暂停的录音功能
- 错误信息 NSError
- 我所理解的c++编程技巧
- 数据结构线性表d
- hdu 4757 Tree(可持久化字典树)
- MySQL添加中文查询结果在乱码的解决方法
- Android开发之如何监听让服务不被杀死(service+broadcast)
- Android SlidingMenu 使用详解
- spring 项目返回406
- 数据结构(C++版)笔记整理——第三章
- android属性android:largeHeap
- Maven使用第三方jar文件的两种方法
- 统计学习方法——CART, Bagging, Random Forest, Boosting