可持久化字典树
来源:互联网 发布:diy相册制作软件 编辑:程序博客网 时间:2024/05/16 11:47
普通模板:
//给出一个长度为N的正整数数组A,再给出Q个查询,每个查询包括3个数,L, R, X (L <= R)。求A[L] 至 A[R] 这R - L + 1个数中,与X 进行异或运算(Xor),得到的最大值是多少? const int N = 50000 + 10;int son[N*35][2], sum[N*35];int root[N];int tot;int len = 31;bool bs[35];//空树的话,所有值都是0,可以直接看作一个点,免去了建空树的过程,要建的话,参考主席树即可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){//此时bs储存的是跟查询值完全相反的二进制位,即查询值要取得异或最大值所需要的二进制位 if(! p) return 0; //此区间内在p-1位置上有需要的二进制位,就加上相应的值,并进入下一层 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)); //p-1位置上没有需要的二进制位,说明这种类型的数字不存在,只能进入另一种类型的数字中去递归查询 return trie_query(p-1, son[st][1-bs[p-1]], son[en][1-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 val, int y, int x)//{// 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]]> 0)// {// ans |= (1 << i);// x = son[x][j], y = son[y][j];// }// else x = son[x][!j], y = son[y][!j];// }// return ans;//}//int main()//{// int n, m, x;// scanf("%d%d", &n, &m);// tot = 0;// for(int i = 1; i <= n; i++)// {// scanf("%d", &x);// root[i] = trie_insert(x, root[i-1]);// }// int l, r;// for(int i = 1; i <= m; i++)// {// scanf("%d%d%d", &x, &l, &r);// l++, r++;// int ans = trie_query(x, root[l-1], root[r]);// printf("%d\n", ans);// }// return 0;//}int main(){ int n, m, x; scanf("%d%d", &n, &m); tot = 0; for(int i = 1; i <= n; i++) { scanf("%d", &x); for(int j = len-1; j >= 0; j--) bs[j] = 1 & (x >> j); trie_insert(len, root[i-1], root[i]); } int l, r; for(int i = 1; i <= m; i++) { scanf("%d%d%d", &x, &l, &r); for(int j = len-1; j >= 0; j--) bs[j] = !(1 & (x >> j)); l++, r++; int ans = trie_query(len, root[l-1], root[r]); printf("%d\n", ans); } return 0;}
树上的模板:
//给出一棵树,树上的点都有权值,每次给出一组询问x y z,求从x到y路径上的点权值和z异或得到的最大值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;}
阅读全文
0 0
- 可持久化字典树
- BZOJ 3261 可持久化字典树
- BZOJ3166 && BZOJ3261 可持久化字典树
- hdu4757(LCA+可持久化字典树)
- 模板 可持久化字典树
- bzoj4546 -- 可持久化字典树
- hdu6191 可持久化字典树
- HDU 4757 可持久化字典树(Trie)
- hdu 4757 Tree(可持久化字典树)
- [可持久化字典树 set] BZOJ 3166 [Heoi2013]Alo
- [可持久化字典树] BZOJ 4546 codechef XRQRS
- bzoj 3166 [Heoi2013]Alo 可持久化字典树
- hdu-4757-Tree-树链剖分+可持久化字典树
- bzoj3261 最大异或和(可持久化字典树)
- Codechef Xor Queries(可持久化字典树)
- Hdu-4757 Tree(可持久化字典树)
- BZOJ3261最大异或和(可持久化字典树)
- BZOJ 3166: [Heoi2013]Alo 可持久化字典树
- LNMP all-in-one
- java中的代理
- 如何使用 Spring MVC 进行单文件与多文件上传的三种情况
- LICEcap GIF屏幕录制工具
- IntelliJ Idea 免费激活方法
- 可持久化字典树
- html里嵌套php
- [Spring事务]
- android webview 加载https --忽略证书
- Chrome 及驱动各版本下载地址
- 自顶向下语法分析方法:消除左递归
- 朴素贝叶斯实现垃圾信息分类
- 前端字符串拼接 优化栈内存
- 第五周项目-建立链栈算法库