HDU - 4757 Tree(LCA+可持久化trie树)
题目链接:点击查看
题目大意:给出一棵有有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树)相关推荐
- BZOJ 3261 最大异或和 可持久化Trie树
题目大意:给定一个序列,提供下列操作: 1.在数组结尾插入一个数 2.给定l,r,x,求一个l<=p<=r,使x^a[p]^a[p+1]^...^a[n]最大 首先我们能够维护前缀和 然后 ...
- 【bzoj3261】最大异或和 可持久化Trie树
题目描述 给定一个非负整数序列 {a},初始长度为 N. 有M个操作,有以下两种操作类型: 1.A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1. 2.Q l r x: ...
- 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 ...
- BZOJ3261 最大异或和 解题报告(可持久化Trie树)
本题链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3261 题目描述 给定一个非负整数序列{a},初始长度为N. 有M个操作,有以下两种操作类 ...
- BZOJ #3166. [Heoi2013]Alo(可持久化trie树+set)
#3166. [Heoi2013]Alo description solution code BZOJ3166 description Welcome to ALO ( Arithmetic and ...
- BZOJ3261: 最大异或和(可持久化trie树)
题意 题目链接 Sol 设\(sum[i]\)表示\(1 - i\)的异或和 首先把每个询问的\(x \oplus sum[n]\)就变成了询问前缀最大值 可持久化Trie树维护前缀xor,建树的时候 ...
- 省选专练(学习)可持久化Trie树(BZOJ3261)
这个似乎也不是好难啊 但是可持久化Trie还是可以干许多线性基不能干的事. 什么是可持久化Trie? 顾名思义:是一种可以持久化的Trie树 他的建树方式和键值式线段树方式类似 也支持版本的减法 查询 ...
- BZOJ3166 [Heoi2013]Alo 【可持久化trie树 + 二分 + ST表】
题目 Welcome to ALO ( Arithmetic and Logistic Online).这是一个VR MMORPG , 如名字所见,到处充满了数学的谜题. 现在你拥有n颗宝石,每颗宝石 ...
- P4735 最大异或和 01可持久化Trie树模板
原题:https://www.luogu.org/problemnew/show/P4735 题解:观察一下式子,将a数组求一个异或前缀和,其实就是s[n]^x^s[p-1]的最大值 p∈[l,r], ...
最新文章
- HTML 5与CSS 3权威指南(第2版·上册)
- 【百度地图API】如何制作一张魔兽地图!!——CS地图也可以,哈哈哈
- doxygen相关问题
- 二分 poj 3273
- Notable magic numbers
- pythonsocket自动化教程_Python基本socket通信控制操作示例
- [bzoj1468][poj1741]Tree_点分治
- 全球顶级金融机构Citadel:堡垒如何建成|精品投行系列二
- MyQQ:可以在终端里面上的QQ
- Microsoft Internet Explorer浏览器包含最新版本的内置Adobe Flash Player的解决办法
- 怎么快速查找重复文件以及删除重复文件
- Java-mail发送邮件
- 面试之NGFW 性能测试
- sitecore系统教程之内容编辑器
- 关于Excel中的自定义格式
- 说谎者的辩白 -卢梭
- leaflet实现动态地图风场效果
- python 小说人物分析_Python文章相关性分析---金庸武侠小说分析
- 服务器io测试工具-fio
- 初识openstack之0——虚拟化及Xen和KVM介绍