首先如果给定一些数,询问这些数中哪个数^给定的数的值最大的话,我们可以建立一颗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树的更多相关文章

  1. 可持久化Trie树初步

    可持久化Trie树和可持久化线段树很像,依次插入信息,通过减法来进行历史版本查询. 2015年11月27日 bzoj3261 最大异或和 我们需要计算 a[p] xor a[p+1] xor ... ...

  2. [十二省联考2019]异或粽子——可持久化trie树+堆

    题目链接: [十二省联考2019]异或粽子 求前$k$大异或区间,可以发现$k$比较小,我们考虑找出每个区间. 为了快速得到一个区间的异或和,将原序列做前缀异或和. 对于每个点作为右端点时,我们维护出 ...

  3. BZOJ4477[Jsoi2015]字符串树——可持久化trie树

    题目描述 萌萌买了一颗字符串树的种子,春天种下去以后夏天就能长出一棵很大的字符串树.字符串树很奇特,树枝上都密密麻麻写满了字符串,看上去很复杂的样子.[问题描述]字符串树本质上还是一棵树,即N个节点N ...

  4. BZOJ5338 [TJOI2018] Xor 【可持久化Trie树】【dfs序】

    题目分析: 很无聊的一道题目.首先区间内单点对应异或值的询问容易想到trie树.由于题目在树上进行,case1将路径分成两段,然后dfs的时候顺便可持久化trie树做询问.case2维护dfs序,对d ...

  5. 51nod 1295 XOR key (可持久化Trie树)

    1295 XOR key  题目来源: HackerRank 基准时间限制:1.5 秒 空间限制:262144 KB 分值: 160 难度:6级算法题   给出一个长度为N的正整数数组A,再给出Q个查 ...

  6. 【BZOJ-4212】神牛的养成计划 Trie树 + 可持久化Trie树

    4212: 神牛的养成计划 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 136  Solved: 27[Submit][Status][Discus ...

  7. 51nod 1295 XOR key | 可持久化Trie树

    51nod 1295 XOR key 这也是很久以前就想做的一道板子题了--学了一点可持久化之后我终于会做这道题了! 给出一个长度为N的正整数数组A,再给出Q个查询,每个查询包括3个数,L, R, X ...

  8. 【bzoj2741】[FOTILE模拟赛]L 可持久化Trie树+分块

    题目描述 FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor A ...

  9. bzoj 3261: 最大异或和 (可持久化trie树)

    3261: 最大异或和 Time Limit: 10 Sec  Memory Limit: 512 MB Description       给定一个非负整数序列 {a},初始长度为 N.       ...

随机推荐

  1. 3dContactPointAnnotationTool开发日志(十二)

      因为ReferenceImage的锚点是固定的左下角,缩放时controller面板也会跟着动.为了使Scale的时候controller上的slider不会远离指针,于是把controller固 ...

  2. 3ds Max学习日记(二)

      搞了一天终于把第二章弄完了,虽然有点慢,但也是没有办法,毕竟中途学累了总得放松一下吧.   又get到了一个新知识点,是关于3ds max的捕捉工具的,详情见3DS MAX 学习笔记 一(捕捉工具 ...

  3. PokeCats开发者日志(十三)

      现在是PokeCats游戏开发的第六十二天的晚上,把软著权登记证书的截图加上,又重新提交审核了一遍,但愿能过吧...

  4. eclipse 创建并运行maven web项目

    这两天想在eclipse上运行maven web项目,折腾了许久,总算success啦. 1,利用eclipse创建dynamic web project(eclipse需要安装m2eclipse). ...

  5. Java-通过比较throw与throws来阐述抛出异常

    转自:http://www.cnblogs.com/Miracle-Maker/p/6239346.html 浅谈Java异常 以前虽然知道一些异常的处理,也用过一些,但是对throw和throws区 ...

  6. shit antd & Merry Christmas bug

    shit antd & Merry Christmas bug https://github.com/ant-design/ant-design/issues/13098 antd 玩大了? ...

  7. vs code 自动补全效果不理想的问题

    之前一直用webstorm,最近换换口味,改用了VS Code,发现VS Code 智能提示得到的都不是我想要的 就比如  ! + tab ,HTML结构都出不来.经过一番搜索,发现是 VS Code ...

  8. Oracle 物化视图创建以及常见问题

    create materialized view MV_XXXXrefresh fast on commitwith rowidenable query rewriteasselect * from ...

  9. BZOJ5319 & 洛谷4559 & LOJ2551:[JSOI2018]军训列队——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=5319 https://www.luogu.org/problemnew/show/P4559 ht ...

  10. 【状压DP】【P3959】【NOIP2017D2T2】宝藏

    Description 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 $n$ 个深埋在地下的宝藏屋, 也给出了这 $n$ 个宝藏屋之间可供开发的$ m$ 条道路和它们的长度. 小明决心亲自前往挖 ...