HDU 4757 可持久化trie树
首先如果给定一些数,询问这些数中哪个数^给定的数的值最大的话,我们可以建立一颗trie树,根连接的两条边分别为0,1,表示二进制下第15位,那么我们可以建立一颗trie树,每一条从根到叶子节点的链表示一个2^16以内的数,开始每个节点的cnt都是0,那么每插入一个元素,将表示这个值的链上所有位置的cnt++,那么对于一个值要求使得^最大,如果这个值的某一位是1,那么我们最好要找到一个为0的数来和他^,那么判断下0儿子的cnt是不是大于0,然后做就好了。
那么对于这棵树,我们可以先将1为根,然后对于两个点x,y之间的链拆成x,lca和y,lca的两条链,现在问题就转化为了求一个深度递增的链上所有值和给定值的^值最大,那么我们可以建立可持久化trie,每个节点继承父节点的trie树,我们只需要用x的trie树减去lca father的trie树做开始的问题就好了。
反思:调试的时候输出调试的,然后答案更新的只按照一部分更新的,忘了改回去了。因为这个题没看题,是别人讲的题意,所以没看到多组数据,在这儿一直错= =。
- //By BLADEVIL
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- #define maxn 200010
- using namespace std;
- struct ww {
- int son[];
- int cnt;
- ww() {
- cnt=;
- memset(son,,sizeof son);
- }
- }t[maxn<<];
- int n,m,l,tot;
- int a[maxn],pre[maxn<<],other[maxn<<],last[maxn],que[maxn],dis[maxn],jump[maxn][];
- void connect(int x,int y) {
- pre[++l]=last[x];
- last[x]=l;
- other[l]=y;
- }
- int lca(int x,int y) {
- if (dis[x]>dis[y]) swap(x,y);
- int dep=dis[y]-dis[x];
- for (int i=;i<=;i++) if (dep&(<<i)) y=jump[y][i];
- if (x==y) return x;
- for (int i=;i>=;i--) if (jump[x][i]!=jump[y][i]) x=jump[x][i],y=jump[y][i];
- return jump[x][];
- }
- void build(int &x,int dep) {
- if (!x) x=++tot;
- if (dep<) return ;
- build(t[x].son[],dep-); build(t[x].son[],dep-);
- }
- void insert(int &x,int rot,int dep,int key) {
- if (!x) x=++tot;
- if (dep==-) return ;
- if (key&(<<dep)) {
- insert(t[x].son[],t[rot].son[],dep-,key);
- t[x].son[]=t[rot].son[];
- } else {
- insert(t[x].son[],t[rot].son[],dep-,key);
- t[x].son[]=t[rot].son[];
- }
- t[x].cnt+=t[rot].cnt+;
- //printf("|%d %d\n",t[x].cnt,x);
- }
- int query(int rx,int lx,int key,int dep) {
- if (dep==-) return ;
- //printf("%d %d %d %d\n",t[rx].son[1],t[rx].son[0],t[t[rx].son[1]].cnt,t[t[rx].son[0]].cnt);
- int ans=;
- if (key&(<<dep)) {
- if (t[t[rx].son[]].cnt-t[t[lx].son[]].cnt) {
- ans=<<dep;
- ans+=query(t[rx].son[],t[lx].son[],key,dep-);
- } else ans=query(t[rx].son[],t[lx].son[],key,dep-);
- } else {
- if (t[t[rx].son[]].cnt-t[t[lx].son[]].cnt) {
- ans=<<dep;
- ans+=query(t[rx].son[],t[lx].son[],key,dep-);
- } else ans=query(t[rx].son[],t[lx].son[],key,dep-);
- }
- //printf("%d\n",ans);
- return ans;
- }
- void work() {
- memset(t,,sizeof t);
- memset(last,,sizeof last);
- memset(dis,,sizeof dis);
- tot=n; l=;
- for (int i=;i<=n;i++) scanf("%d",&a[i]);
- for (int i=;i<n;i++) {
- int x,y; scanf("%d%d",&x,&y);
- connect(x,y); connect(y,x);
- }
- int head=,tail=; que[]=; dis[]=;
- while (head<tail) {
- int cur=que[++head];
- for (int p=last[cur];p;p=pre[p]) {
- if (dis[other[p]]) continue;
- que[++tail]=other[p]; dis[other[p]]=dis[cur]+;
- }
- }
- //for (int i=1;i<=n;i++) printf(i==n?"%d\n":"%d ",que[i]);
- jump[][]=++tot;
- for (int i=;i<=n;i++)
- for (int p=last[que[i]];p;p=pre[p])
- if (dis[other[p]]>dis[que[i]]) jump[other[p]][]=que[i];
- for (int i=;i<=;i++)
- for (int j=;j<=n;j++){
- int cur=que[j];
- jump[cur][i]=jump[jump[cur][i-]][i-];
- }
- build(jump[][],);
- for (int i=;i<=n;i++) insert(que[i],jump[que[i]][],,a[que[i]]);
- //for (int i=1;i<=tot;i++) printf("%d %d %d %d\n",i,t[i].son[0],t[i].son[1],t[i].cnt);
- //int x,y; scanf("%d%d",&x,&y); printf("%d\n",lca(x,y));
- while (m--) {
- int x,y,z; scanf("%d%d%d",&x,&y,&z);
- int root=lca(x,y);
- int ans=;
- ans=max(query(x,jump[root][],z,),query(y,jump[root][],z,));
- //ans=query(y,jump[root][0],z,15);
- printf("%d\n",ans);
- }
- }
- int main() {
- while (scanf("%d%d",&n,&m)!=EOF) work();
- return ;
- }
HDU 4757 可持久化trie树的更多相关文章
- 可持久化Trie树初步
可持久化Trie树和可持久化线段树很像,依次插入信息,通过减法来进行历史版本查询. 2015年11月27日 bzoj3261 最大异或和 我们需要计算 a[p] xor a[p+1] xor ... ...
- [十二省联考2019]异或粽子——可持久化trie树+堆
题目链接: [十二省联考2019]异或粽子 求前$k$大异或区间,可以发现$k$比较小,我们考虑找出每个区间. 为了快速得到一个区间的异或和,将原序列做前缀异或和. 对于每个点作为右端点时,我们维护出 ...
- BZOJ4477[Jsoi2015]字符串树——可持久化trie树
题目描述 萌萌买了一颗字符串树的种子,春天种下去以后夏天就能长出一棵很大的字符串树.字符串树很奇特,树枝上都密密麻麻写满了字符串,看上去很复杂的样子.[问题描述]字符串树本质上还是一棵树,即N个节点N ...
- BZOJ5338 [TJOI2018] Xor 【可持久化Trie树】【dfs序】
题目分析: 很无聊的一道题目.首先区间内单点对应异或值的询问容易想到trie树.由于题目在树上进行,case1将路径分成两段,然后dfs的时候顺便可持久化trie树做询问.case2维护dfs序,对d ...
- 51nod 1295 XOR key (可持久化Trie树)
1295 XOR key 题目来源: HackerRank 基准时间限制:1.5 秒 空间限制:262144 KB 分值: 160 难度:6级算法题 给出一个长度为N的正整数数组A,再给出Q个查 ...
- 【BZOJ-4212】神牛的养成计划 Trie树 + 可持久化Trie树
4212: 神牛的养成计划 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 136 Solved: 27[Submit][Status][Discus ...
- 51nod 1295 XOR key | 可持久化Trie树
51nod 1295 XOR key 这也是很久以前就想做的一道板子题了--学了一点可持久化之后我终于会做这道题了! 给出一个长度为N的正整数数组A,再给出Q个查询,每个查询包括3个数,L, R, X ...
- 【bzoj2741】[FOTILE模拟赛]L 可持久化Trie树+分块
题目描述 FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor A ...
- bzoj 3261: 最大异或和 (可持久化trie树)
3261: 最大异或和 Time Limit: 10 Sec Memory Limit: 512 MB Description 给定一个非负整数序列 {a},初始长度为 N. ...
随机推荐
- 解决ueditor编辑器图片在线管理图片无法显示
使用ueditor,点击在线管理,服务器图片路径显示不正确,如下图所示 查看源码,如下: 发现图片src中中间多了一长串的项目跟路径,解决的办法是 把 jsp/controller.jsp 里面 ...
- C# 使用this的形参
示例1: public static RectangleF TransformRect(this Matrix mat, RectangleF rect) 是向Matrix类扩展带有Rectangle ...
- 选择正确的C/C++ runtime library
本文是对http://www.davidlenihan.com/2008/01/choosing_the_correct_cc_runtim.html的翻译,如有错误,还请指正 c/c++运行库(ru ...
- DELPHI BOOKMARK使用
关于书签(BookMark)操作: 书签操作主要用于在表中快速地定位记录指针,在应用程序中常常要保存记录指针所在的位置,在进行其他处理之后,希望能快速地返回到先前指针所在的位置,此时,使用 ...
- 【bzoj2223】[Coci 2009]PATULJCI 主席树
题目描述 样例输入 10 3 1 2 1 2 1 2 3 2 3 3 8 1 2 1 3 1 4 1 5 2 5 2 6 6 9 7 10 样例输出 no yes 1 no yes 1 no yes ...
- python-输出颜色显示
显示颜色格式:\033[显示方式;字体色;背景色m...主题内容hello world...\033[0m \033 从这里开始标颜色................................. ...
- [bzoj] 2049 洞穴勘探 || LCT
原题 这是一道LCT的板子题. 至于LCT--link cut tree,也叫动态树,用splay实现动态连边的树. 预备知识: 实边:一个非叶节点,向它的儿子中的一个连一条特殊的边,称为实边;该非叶 ...
- BZOJ3437 小P的牧场 【斜率优化dp】
3437: 小P的牧场 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 1502 Solved: 836 [Submit][Status][Disc ...
- bzoj1968: [Ahoi2005]COMMON 约数研究(数论)
计算每一个数的贡献就好了..O(N) n/i只有2*sqrtn个取值于是可以优化到O(sqrtn) #include<bits/stdc++.h> #define ll long long ...
- 【DP】【Uva437】UVA437 The Tower of Babylon
传送门 Description Input Output Sample Input Sample Output Case : maximum height = Case : maximum heigh ...