首先如果给定一些数,询问这些数中哪个数^给定的数的值最大的话,我们可以建立一颗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. animate.css与wow.js制作网站动效

    animate.css 官网:https://daneden.github.io/animate.css/ 包括:attention seekers:关注者 bouncing entrances:跳跃 ...

  2. nginx 设置默认虚拟 host

    nginx 设置默认虚拟 host listren 80 default_server

  3. Flink的序列化与flink-hadoop-compatibility

    最近 用户提交了一个问题 说他的jar包里明明包含相关的类型 但是在提交Flink作业的时候 却报出classnotfound的错误 查看之后发现 这里是flink的一个没有说的太明白的地方 用户的代 ...

  4. tcp传送报文

    707 void tcp_init_xmit_timers(struct sock *sk)708 {709     inet_csk_init_xmit_timers(sk, &tcp_wr ...

  5. TCP协议详解7层和4层解析(美团,阿里) 尤其是三次握手,四次挥手 具体发送的报文和状态都要掌握

    如果想了解HTTP的协议结构,原理,post,get的区别(阿里面试题目),请参考:HTTP协议 结构,get post 区别(阿里面试) 这里有个大白话的解说,可以参考:TCP/IP协议三次握手和四 ...

  6. VS2012完全卸载

    1.先交VS2012的ISO通过Ultraiso载入2.DOS命中输入 I:\vs_ultimate.exe /uninstall /force 或 I:vs_ultimate.exe /uninst ...

  7. jsp当做第二个servlet request的生命周期 请求 响应 不管中间经历多少个servlet 只要最后一个serlvt执行后 则生命周期结束 request的域消失

    jsp当做第二个servlet  request的生命周期   请求 响应  不管中间经历多少个servlet 只要最后一个serlvt执行后 则生命周期结束  request的域消失

  8. mysql 迁移 mariadb

    背景: mysql5.7数据库安装在windows环境中,数据需要迁移到CentOS7.4的mariadb5.5中.web应用是采用springboot2.x开发的,迁移数据完成后,还需要简单修改一些 ...

  9. BZOJ3680 & 洛谷1337:[JSOI2004]平衡点/吊打XXX——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=3680 https://www.luogu.org/problemnew/show/P1337 有n ...

  10. 欢迎大家收听喜马拉雅,我的主播频道http://m.ximalaya.com/weizhubo/44966139

    关注光荣之路软件技术培训账号,即时收取测试开发技术的免费公开课信息,各大公司测试及开发招聘信息.最新的技术咨询.线下测试 喜马拉雅微电台,每天早晨光荣之路创始人吴老,都会跟大家一起分享测试行业心得体会 ...