首先如果给定一些数,询问这些数中哪个数^给定的数的值最大的话,我们可以建立一颗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. 使用cookies模拟登陆

    http://blog.csdn.net/a1099439833/article/details/51918955 使用cookies会话跟踪,保持cookies访问,对于cookies会失效的问题可 ...

  2. PHP获取网页内容的几种方法

    方法1: 用file_get_contents以get方式获取内容 <?php $url='http://www.domain.com/?para=123'; $html= file_get_c ...

  3. 《Effective C#》快速笔记(四)- 使用框架

    .NET 是一个类库,你了解的越多,自己需要编写的代码就越少. 目录 三十.使用重写而不是事件处理函数 三十一.使用 IComparable<T> 和 IComparer<T> ...

  4. 发生dev_queue_xmit的时候,全部都是从ip_finish_output中来的吗

    也就是说啊,内核中的收发包的路径,很可能是经理driver_recv --> tcp -->driver_send这样一个过程,是个很长的路径呢...... 从dev_queue_xmit ...

  5. 面试:谈谈你对jQuery的理解

    jQuery是一个轻量级的javascript框架,极大的简化了js的编程. 1.首先jQuery提供了强大的元素选择器.用于获取html页面中封装了html元素的jQuery对象.像常见的选择器有: ...

  6. 微信支付java

    直接上代码: 1.支付配置PayCommonUtil import com.legendshop.payment.tenpay.util.MD5Util; import com.legendshop. ...

  7. 如何取得dbgrid中未保存(post)的值(50分)

    比如说处在编辑状态时,想取得当前记录值 Dataset.fields[0].Value 就是当前值:Dataset.fields[0].OldValue 就是原始值. 呵呵,我指得是在编辑时,就是按键 ...

  8. [转]MATLAB cell数据类型

    细胞型数据类型(cell)使不同类型和不同维数的数组可以共存,细胞型数组实际上可以认为是一种以任意形式的数组为分量的多维数组. 1.细胞型数据的定义 1)直接赋值定义:细胞型变量在定义时需要使用大括号 ...

  9. hdu 1848(Fibonacci again and again)(SG博弈)

    Fibonacci again and again Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Jav ...

  10. POJ 3261 Milk Patterns (后缀数组,求可重叠的k次最长重复子串)

    Milk Patterns Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 16742   Accepted: 7390 Ca ...