HDU 4757 Tree 可持久化trie+lca
来源:互联网 发布:淘宝购物的金钱过程 编辑:程序博客网 时间:2024/06/05 10:35
题目:
http://acm.hdu.edu.cn/showproblem.php?pid=4757
题意:
给出一棵树,树上的点都有权值,每次给出一组询问
思路:
可持久化
#include <bits/stdc++.h>using namespace std;const int N = 100000 + 10, INF = 0x3f3f3f3f;int tot, root[N];int son[N*35][2], sum[N*35];int cnt, head[N];int dep[N], p[N][25];int a[N];bool bs[35];int len = 31;struct edge{ int to, next;}g[N*2];void init(){ cnt = 0; memset(head, -1, sizeof head); tot = 0;}void add_edge(int v, int u){ g[cnt].to = u, g[cnt].next = head[v], head[v] = cnt++;}void trie_insert(int p, int pre, int &x){ x = ++tot; son[x][0] = son[pre][0], son[x][1] = son[pre][1]; //memcpy(son[x], son[pre], sizeof(int) * 2); sum[x] = sum[pre] + 1; if(! p) return; trie_insert(p-1, son[pre][bs[p-1]], son[x][bs[p-1]]);}int trie_query(int p, int st, int en){ if(! p) return 0; if(sum[son[en][bs[p-1]]] > sum[son[st][bs[p-1]]]) return trie_query(p-1, son[st][bs[p-1]], son[en][bs[p-1]]) + (1<<(p-1)); return trie_query(p-1, son[st][1-bs[p-1]], son[en][1-bs[p-1]]);}void dfs(int v, int fa, int d){ dep[v] = d, p[v][0] = fa; for(int i = len-1; i >= 0; i--) bs[i] = 1 & (a[v] >> i); trie_insert(len, root[fa], root[v]); for(int i = head[v]; i != -1; i = g[i].next) { int u = g[i].to; if(u == fa) continue; dfs(u, v, dep[v] + 1); }}void lca_init(int n){ for(int j = 1; (1<<j) <= n; j++) for(int i = 1; i <= n; i++) p[i][j] = p[p[i][j-1]][j-1];}int LCA(int v, int u){ if(dep[v] < dep[u]) swap(v, u); int d = dep[v] - dep[u]; for(int i = 0; (d>>i) != 0; i++) if((d>>i) & 1) v = p[v][i]; if(v == u) return v; for(int i = 20; i >= 0; i--) if(p[v][i] != p[u][i]) v = p[v][i], u = p[u][i]; return p[v][0];}int main(){ int n, m; while(~ scanf("%d%d", &n, &m)) { init(); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = 1; i <= n-1; i++) { int v, u; scanf("%d%d", &v, &u); add_edge(v, u); add_edge(u, v); } dfs(1, 0, 1); lca_init(n); for(int i = 1; i <= m; i++) { int x, y, val; scanf("%d%d%d", &x, &y, &val); for(int j = len-1; j >= 0; j--) bs[j] = ! (1 & (val >> j)); int lca = LCA(x, y); int ans = trie_query(len, root[p[lca][0]], root[x]); ans = max(ans, trie_query(len, root[p[lca][0]], root[y])); printf("%d\n", ans); } } return 0;}
写了个非递归版的插入和查询,好像快了一些。。。
#include <bits/stdc++.h>using namespace std;const int N = 100000 + 10, INF = 0x3f3f3f3f;int tot, root[N];int son[N*35][2], sum[N*35];int cnt, head[N];int dep[N], p[N][25];int a[N];bool bs[35];int len = 31;struct edge{ int to, next;}g[N*2];void init(){ cnt = 0; memset(head, -1, sizeof head); tot = 0;}void add_edge(int v, int u){ g[cnt].to = u, g[cnt].next = head[v], head[v] = cnt++;}//void trie_insert(int p, int pre, int &x)//{// x = ++tot;// son[x][0] = son[pre][0], son[x][1] = son[pre][1];// //memcpy(son[x], son[pre], sizeof(int) * 2);// sum[x] = sum[pre] + 1;// if(! p) return;// trie_insert(p-1, son[pre][bs[p-1]], son[x][bs[p-1]]);//}int trie_insert(int val, int pre){ int x = ++tot, t = x; for(int i = len-1; i >= 0; i--) { son[x][0] = son[pre][0], son[x][1] = son[pre][1]; sum[x] = sum[pre] + 1; int j = 1 & (val >> i); son[x][j] = ++tot; x = son[x][j], pre = son[pre][j]; } sum[x] = sum[pre] + 1; return t;}//int trie_query(int p, int st, int en)//{// if(! p) return 0;// if(sum[son[en][bs[p-1]]] > sum[son[st][bs[p-1]]]) return trie_query(p-1, son[st][bs[p-1]], son[en][bs[p-1]]) + (1<<(p-1));// return trie_query(p-1, son[st][1-bs[p-1]], son[en][1-bs[p-1]]);//}void dfs(int v, int fa, int d){ dep[v] = d, p[v][0] = fa;// for(int i = len-1; i >= 0; i--) bs[i] = 1 & (a[v] >> i);// trie_insert(len, root[fa], root[v]); root[v] = trie_insert(a[v], root[fa]); for(int i = head[v]; i != -1; i = g[i].next) { int u = g[i].to; if(u == fa) continue; dfs(u, v, dep[v] + 1); }}void lca_init(int n){ for(int j = 1; (1<<j) <= n; j++) for(int i = 1; i <= n; i++) p[i][j] = p[p[i][j-1]][j-1];}int LCA(int v, int u){ if(dep[v] < dep[u]) swap(v, u); int d = dep[v] - dep[u]; for(int i = 0; (d>>i) != 0; i++) if((d>>i) & 1) v = p[v][i]; if(v == u) return v; for(int i = 20; i >= 0; i--) if(p[v][i] != p[u][i]) v = p[v][i], u = p[u][i]; return p[v][0];}int trie_query(int x, int y, int val){ int lca = LCA(x, y), lca_fa = p[lca][0]; x = root[x], y = root[y], lca = root[lca], lca_fa = root[lca_fa]; int ans = 0; for(int i = len-1; i >= 0; i--) { int j = !(1 & (val >> i)); if(sum[son[x][j]] + sum[son[y][j]] - sum[son[lca][j]] - sum[son[lca_fa][j]] > 0) { ans |= (1 << i); x = son[x][j], y = son[y][j], lca = son[lca][j], lca_fa = son[lca_fa][j]; } else x = son[x][!j], y = son[y][!j], lca = son[lca][!j], lca_fa = son[lca_fa][!j]; } return ans;}int main(){ int n, m; while(~ scanf("%d%d", &n, &m)) { init(); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = 1; i <= n-1; i++) { int v, u; scanf("%d%d", &v, &u); add_edge(v, u); add_edge(u, v); } dfs(1, 0, 1); lca_init(n); for(int i = 1; i <= m; i++) { int x, y, val; scanf("%d%d%d", &x, &y, &val);// for(int j = len-1; j >= 0; j--) bs[j] = ! (1 & (val >> j));// int lca = LCA(x, y);// int ans = trie_query(len, root[p[lca][0]], root[x]);// ans = max(ans, trie_query(len, root[p[lca][0]], root[y])); int ans = trie_query(x, y, val); printf("%d\n", ans); } } return 0;}
阅读全文
0 0
- HDU 4757 Tree 可持久化trie+lca
- hdu 4757 Tree(可持久化Trie)
- HDU 4757 Tree (倍增算法求LCA + 可持久化Trie树)
- [HDU4757][可持久化Trie][LCA]Tree[好题]
- HDU 4757 可持久化trie树
- HDU 6191 Query on A Tree 可持久化trie + dfs建树 || 启发式合并trie
- HDU 4757 可持久化字典树(Trie)
- HDU-5801 可持久化Trie树
- HDU 6191 Query on A Tree (dfs序+可持久化01Trie)
- 可持久化trie
- hdu 4757 Tree(可持久化字典树)
- hdu-4757-Tree-树链剖分+可持久化字典树
- Hdu-4757 Tree(可持久化字典树)
- hdu 4757 Tree(可持久化字典树)
- hdu 6191 可持久化trie||线段树套trie||trie启发式合并
- [BZOJ3261]-可持久化trie
- 2588: Spoj 10628. Count on a tree[可持久化线段树+倍增lca]
- 【BZOJ2588】【Spoj 10628.】 Count on a tree 可持久化线段树+lca
- 深度学习DeepLearning.ai系列课程学习总结:4. Logistic代码实战
- 如何使用泛型和索引器实现集合类List
- 消息中间件核心实体(0)
- 超详细git教程 GitHub创建管理仓库教程
- 招对合适的网络营销推广人才
- HDU 4757 Tree 可持久化trie+lca
- Qt 第6章 布局管理(3) 切分布局管理 学习笔记
- 面试题(1)
- 2017年9月2日普级组T1 正方形
- 又是考查内存对齐和指针理解, 简单东西。
- python学习——函数返回值及递归
- Matlab实现均匀量化的简单实例
- HDU2665 POJ2104 K-th Number(主席树)
- TCP的三次握手和四次挥手