题目链接:点击查看

题目大意:给出一棵有有n个节点的树,每个点都有一个权值,现在给出m个查询,每次查询的形式为:x,y,z,求出从点x到点y的路径上任选一点,使其与z的异或值最大,输出异或值

题目分析:一开始看到从一个区间内任选一个点与指定的值异或取最值,立马就想到了可持久化trie树,可是这个题目是基于树上操作的,我们该怎么将树上的路径拿下来呢?其实这就涉及到了LCA,在给出两个点x和y后,只需要求出两个点的lca,就可以将x到y的路径分为了x到lca的路径+y到lca的路径了,由于lca的深度肯定小于等于x和y中的任何一个值,所以我们就可以将x到y的路径分为两个区间了:[lca,x]和[lca,y],这样就能使两个算法配合操作了

关于在树上建可持久化字典树,我们只需要从根节点开始遍历,然后每次利用父节点的root继承就可以了,因为我们需要的区间是

[lca,x]和[lca,y],而可持久化的数据结构可以当做前缀和来理解,所以最后我们提供的点应该是[fa[lca],x]和[fa[lca],y],fa数组代表的是当前节点的父节点,这样就能达到前缀和作差的形式了

通过这个题真的学到了很多,先是抛开所需要的算法lca和可持久化字典树不说,首先也是默写代码的一种能力,然后是调试的能力,因为一开始把lca函数中的deep[a]和deep[b]写反了导致样例都跑不出来,还有就是对各个函数更加理解了,在调试的过程中,亲手将一个递归程序换成了循环来写,也是更进一步的理解了可持久化字典树这个数据结构吧,也不枉我调了三个小时,期间和zx学长学到了好多比较先进的知识,首先在初始化时不需要用memset对trie和sum两个比较大的数组直接初始化,我们可以定义一个newnode函数,用来在使用之前初始化这两个数组,还有就是在求lca时,可以稍微暴力一点,也暴力不到那里去,一开始定义的范围可以根据n来确定,下限是0毋庸置疑,上限我们可以设置为log2(n)+1,这样的话可以保证对于较小程序的合理性

不多说了,上代码:

#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
#include<unordered_map>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e5+100;int n,m;int head[N];int a[N];//每个点的权值 int deep[N],fa[N];//每个点的深度和父节点 int dp[N][20];//倍增 int trie[N*17][2];//字典树 int sum[N*17];int root[N];int cnt,tot,k;struct edge
{int to,next;
}edge[N*2];void addedge(int u,int v)
{edge[tot].to=v;edge[tot].next=head[u];head[u]=tot++;edge[tot].to=u;edge[tot].next=head[v];head[v]=tot++;
}int LCA(int a,int b)
{if(deep[a]<deep[b])swap(a,b);for(int i=k;i>=0;i--)if(deep[a]-deep[b]>=(1<<i))a=dp[a][i];if(a==b)return a;for(int i=k;i>=0;i--)if(dp[a][i]!=dp[b][i]){a=dp[a][i];b=dp[b][i];}return dp[a][0];
}int newnode()
{cnt++;trie[cnt][0]=trie[cnt][1]=0;sum[cnt]=0;return cnt;
}void insert(int pre,int &cur,int step,int x)
{cur=newnode();trie[cur][0]=trie[pre][0];trie[cur][1]=trie[pre][1];sum[cur]=sum[pre]+1;if(step<0)return;int to=(x>>step)&1;insert(trie[pre][to],trie[cur][to],step-1,x);
}int query(int l,int r,int step,int x)
{if(step<0)return 0;int to=(x>>step)&1;if(sum[trie[r][!to]]-sum[trie[l][!to]]>0)return query(trie[l][!to],trie[r][!to],step-1,x)+(1<<step);elsereturn query(trie[l][to],trie[r][to],step-1,x);
}void dfs(int u,int f,int dep)
{insert(root[f],root[u],15,a[u]);deep[u]=dep;fa[u]=f;dp[u][0]=f;for(int i=1;i<=k;i++)dp[u][i]=dp[dp[u][i-1]][i-1];for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;if(v==f)continue;dfs(v,u,dep+1);}
}void init()
{memset(head,-1,sizeof(head));cnt=0;tot=0;k=log2(n)+1;
}int main()
{
//  freopen("input.txt","r",stdin);
//    ios::sync_with_stdio(false);while(scanf("%d%d",&n,&m)!=EOF){init();for(int i=1;i<=n;i++)scanf("%d",a+i);for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);addedge(u,v);}dfs(1,0,0);while(m--){int u,v,x;scanf("%d%d%d",&u,&v,&x);int lca=LCA(u,v);printf("%d\n",max(query(root[fa[lca]],root[u],15,x),query(root[fa[lca]],root[v],15,x)));}}return 0;
}

HDU - 4757 Tree(LCA+可持久化trie树)相关推荐

  1. BZOJ 3261 最大异或和 可持久化Trie树

    题目大意:给定一个序列,提供下列操作: 1.在数组结尾插入一个数 2.给定l,r,x,求一个l<=p<=r,使x^a[p]^a[p+1]^...^a[n]最大 首先我们能够维护前缀和 然后 ...

  2. 【bzoj3261】最大异或和 可持久化Trie树

    题目描述 给定一个非负整数序列 {a},初始长度为 N.        有M个操作,有以下两种操作类型: 1.A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1. 2.Q l r x: ...

  3. P4735 最大异或和(可持久化trie树、求最大区间异或和)

    P4735 最大异或和 我们维护一个前缀异或和:s[i]=a[1]xora[2]xor-a[i−1]xora[i]s[i] = a[1] \ xor\ a[2]\ xor\ - a[i-1] \ xo ...

  4. BZOJ3261 最大异或和 解题报告(可持久化Trie树)

    本题链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3261 题目描述 给定一个非负整数序列{a},初始长度为N. 有M个操作,有以下两种操作类 ...

  5. BZOJ #3166. [Heoi2013]Alo(可持久化trie树+set)

    #3166. [Heoi2013]Alo description solution code BZOJ3166 description Welcome to ALO ( Arithmetic and ...

  6. BZOJ3261: 最大异或和(可持久化trie树)

    题意 题目链接 Sol 设\(sum[i]\)表示\(1 - i\)的异或和 首先把每个询问的\(x \oplus sum[n]\)就变成了询问前缀最大值 可持久化Trie树维护前缀xor,建树的时候 ...

  7. 省选专练(学习)可持久化Trie树(BZOJ3261)

    这个似乎也不是好难啊 但是可持久化Trie还是可以干许多线性基不能干的事. 什么是可持久化Trie? 顾名思义:是一种可以持久化的Trie树 他的建树方式和键值式线段树方式类似 也支持版本的减法 查询 ...

  8. BZOJ3166 [Heoi2013]Alo 【可持久化trie树 + 二分 + ST表】

    题目 Welcome to ALO ( Arithmetic and Logistic Online).这是一个VR MMORPG , 如名字所见,到处充满了数学的谜题. 现在你拥有n颗宝石,每颗宝石 ...

  9. P4735 最大异或和 01可持久化Trie树模板

    原题:https://www.luogu.org/problemnew/show/P4735 题解:观察一下式子,将a数组求一个异或前缀和,其实就是s[n]^x^s[p-1]的最大值 p∈[l,r], ...

最新文章

  1. HTML 5与CSS 3权威指南(第2版·上册)
  2. 【百度地图API】如何制作一张魔兽地图!!——CS地图也可以,哈哈哈
  3. doxygen相关问题
  4. 二分 poj 3273
  5. Notable magic numbers
  6. pythonsocket自动化教程_Python基本socket通信控制操作示例
  7. [bzoj1468][poj1741]Tree_点分治
  8. 全球顶级金融机构Citadel:堡垒如何建成|精品投行系列二
  9. MyQQ:可以在终端里面上的QQ
  10. Microsoft Internet Explorer浏览器包含最新版本的内置Adobe Flash Player的解决办法
  11. 怎么快速查找重复文件以及删除重复文件
  12. Java-mail发送邮件
  13. 面试之NGFW 性能测试
  14. sitecore系统教程之内容编辑器
  15. 关于Excel中的自定义格式
  16. 说谎者的辩白 -卢梭
  17. leaflet实现动态地图风场效果
  18. python 小说人物分析_Python文章相关性分析---金庸武侠小说分析
  19. 服务器io测试工具-fio
  20. 初识openstack之0——虚拟化及Xen和KVM介绍

热门文章

  1. 运行效果演示-修改applcation-db.xml 文件
  2. 高仿真的类-自动注入
  3. Hive的安装-Hive的交互方式
  4. 日志规范之为什么要使用SLF4J
  5. SasSHRM中基于shiro的认证授权:系统微服务配置shiro
  6. 设计模式之_Strategy_03
  7. jvm_垃圾收集算法讲解(二)
  8. 【代码块】代码块使用注意事项和细节讨论
  9. 使用支持向量机进行光学字符识别_从零推导支持向量机 (SVM)
  10. ubuntu 拷贝文件