HDU4757 Tree(可持久化Trie)
写过可持久化线段树,但是从来没写过可持久化的Trie,今天补一补。
题目就是典型的给你一个数x,和一个数集,问x和里面的某个数xor起来的最大值是多少。
最原始的是数集是固定的,只需要对数集按照高到低位去建Trie,然后贪心匹配就可以了。
这里则是对树上路径的操作,其实也是一样的,对每个节点x维护root到x的Trie,然后纪录下往左走往右走的叶子节点个数,设z=lca(x,y),那么到了个某个节点能否往某个儿子走的限制条件是 sz[ch[x][c]]+sz[ch[y][c]]-2*sz[ch[z][c]]>0,这样说明下面是存在c的儿子的,接着往下走即可。当然这样算其实是会漏掉lca的,所以最后还要和lca取最大值。
区间的询问作为这题的特例同理也是可以处理的。
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <string>
- #include <algorithm>
- #include <cmath>
- #include <queue>
- #include <cassert>
- #include <vector>
- #include <set>
- using namespace std;
- #define maxn 120000
- #define maxnode 2200000
- #define maxlogv 16
- vector<int> G[maxn];
- int n,m;
- int a[maxn];
- int f[maxlogv+2][maxn];
- int dep[maxn];
- int ch[maxnode][2];
- int sz[maxnode];
- int tot;
- int root[maxn];
- int newnode(){
- memset(ch[tot],0,sizeof(ch[tot]));
- sz[tot]=0;
- return tot++;
- }
- // insert val for x with father as y
- void insert(int x,int y,int val)
- {
- x=root[x];y=root[y];
- for(int i=15;i>=0;--i){
- int c=(val>>i)&1;
- if(!ch[x][c]){
- int id=newnode();
- ch[x][c]=id;
- ch[x][!c]=ch[y][!c];
- sz[ch[x][c]]=sz[ch[y][c]];
- }
- x=ch[x][c],y=ch[y][c];
- ++sz[x];
- }
- }
- void dfs(int u,int fa)
- {
- f[0][u]=fa;dep[u]=dep[fa]+1;
- root[u]=newnode();
- insert(u,fa,a[u]);
- for(int i=0;i<G[u].size();++i){
- int v=G[u][i];
- if(v==fa) continue;
- dfs(v,u);
- }
- }
- int lca(int u,int v)
- {
- if(dep[u]>dep[v]) swap(u,v);
- for(int k=0;k<maxlogv;++k){
- if( (dep[v]-dep[u])>>k&1){
- v=f[k][v];
- }
- }
- if(u==v) return u;
- for(int k=maxlogv-1;k>=0;--k){
- if(f[k][u]!=f[k][v]){
- u=f[k][u];
- v=f[k][v];
- }
- }
- return f[0][u];
- }
- int query(int x,int y,int val)
- {
- int z=lca(x,y);int res=a[z]^val;
- x=root[x],y=root[y],z=root[z];
- int ret=0;
- for(int i=15;i>=0;--i){
- int c=(val>>i)&1;
- if(sz[ch[x][!c]]+sz[ch[y][!c]]-2*sz[ch[z][!c]]>0){
- ret+=1<<i;
- c=!c;
- }
- x=ch[x][c];
- y=ch[y][c];
- z=ch[z][c];
- }
- return max(ret,res);
- }
- int main()
- {
- while(cin>>n>>m){
- for(int i=1;i<=n;++i){
- scanf("%d",a+i);
- G[i].clear();
- }
- int ui,vi;
- for(int i=0;i<n-1;++i){
- scanf("%d%d",&ui,&vi);
- G[ui].push_back(vi);
- G[vi].push_back(ui);
- }
- memset(root,0,sizeof(root));
- tot=1;
- memset(f,0,sizeof(f));
- memset(sz,0,sizeof(sz));
- dep[0]=0;
- dfs(1,0);
- for(int k=0;k+1<maxlogv;++k){
- for(int v=1;v<=n;++v){
- if(f[k][v]==0) f[k+1][v]=0;
- else f[k+1][v]=f[k][f[k][v]];
- }
- }
- int xi,yi,zi;
- for(int i=0;i<m;++i){
- scanf("%d%d%d",&xi,&yi,&zi);
- printf("%d\n",query(xi,yi,zi));
- }
- }
- return 0;
- }
HDU4757 Tree(可持久化Trie)的更多相关文章
- HDU.4757.Tree(可持久化Trie)
题目链接 \(Description\) 给定一棵树,点有点权.\(Q\)次询问\(x,y,z\),求\(x\)到\(y\)的简单路径中,与\(z\)异或能得到的最大的数是多少. \(Solution ...
- hdu4757(可持久化 Trie )
hdu4757 题意 给出一棵树,每个节点有权值,每次查询节点 \((u, v)\) 以及 \(x\) ,问 \(u\) 到 \(v\) 路径上的某个节点与 \(x\) 异或最大的值是多少. 分析 T ...
- Hdu-4757 Tree(可持久化字典树+lca)
题目链接:点这 我的github地址:点这 Problem Description Zero and One are good friends who always have fun wi ...
- HDU 4757 Tree(可持久化Trie+Tarjan离线LCA)
Tree Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others) Total Su ...
- HDU 4757 Tree(可持久化trie)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4757 题意:给出一棵树,节点有权值.每次询问x到y的路径上与z抑或的最大值. 思路:可持久化trie. ...
- HDU 6191 Query on A Tree ( 2017广西邀请赛 && 可持久化Trie )
题目链接 题意 : 给你一棵树.树上的每个点都有点权.之后有若干次问询.每次问询给出一个节点编号以及一个整数 X .问你以给出节点为根的子树中哪个节点和 X 异或最大.输出这个值 分析 : 看到这种树 ...
- HDU4757--Tree 可持久化trie + LCA
题意:n个点的树,Q次询问,询问u-v路径上的点的权值与z抑或的最大值. 先考虑,在一个区间上的问题,可以先建一个可持久化的Trie,然后每次询问,就和线段树的操作差不多,从最高位开始考虑选1还是选0 ...
- hdu 6191--Query on A Tree(持久化字典树)
题目链接 Problem Description Monkey A lives on a tree, he always plays on this tree. One day, monkey A l ...
- 可持久化 trie 的简单入门
可持久化 $trie$ ....又是一个表里不一的东西..... 可持久化 $trie$ 的介绍: 和主席树类似的,其实可持久化就是体现在前缀信息的维护上(搞不懂这怎么就叫做可持久化了...) $ ...
随机推荐
- POJ 2299 Ultra-QuickSort 简单题解
Ultra-QuickSort Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 68874 Accepted: 25813 ...
- Broken robot CodeForces - 24D (概率DP)
You received as a gift a very clever robot walking on a rectangular board. Unfortunately, you unders ...
- 使用观察者模式更新Fragment的内容
最近有个需求,就是在Fragment没有切换的时候(show,hide)更新Fragment显示的内容,想了一会,终于想到可以用观察者模式来解决这个问题的. 定义一个[被观察者(接口)]: publi ...
- android抓取logcat日志的方法
这几天帮忙测试一个APP,报告结果需要提交日志文件,于是百度了下安卓的获取日志方法,其实很简单,7个步骤搞定,下面把我的总结分享给大家. 1.下载adb工具包 https://pan.baidu.co ...
- Java类和对象 详解(一)---写的很好通俗易懂---https://blog.csdn.net/wei_zhi/article/details/52745268
https://blog.csdn.net/wei_zhi/article/details/52745268
- Python基础-week06 面向对象编程基础
一.面向对象编程 1.面向过程 与 面向对象编程 面向过程的程序设计: 核心是 过程二字,过程指的是解决问题的步骤,即先干什么再干什么......面向过程的设计就好比精心设计好一条流水线,是一种机械式 ...
- PHP 删除 url 中的 query string
function removeQueryStringFromUrl($url) { if (substr($url,0,4) =="http") { $urlPartsArray ...
- js 遍历对象属性(for in、Object.keys、Object.getOwnProperty) 以及高效地输出 js 数组
js中几种遍历对象的方法,包括for in.Object.keys.Object.getOwnProperty,它们在使用场景方面各有不同. for in 主要用于遍历对象的可枚举属性,包括自有属性. ...
- [转]核函数K(kernel function)
1 核函数K(kernel function)定义 核函数K(kernel function)就是指K(x, y) = <f(x), f(y)>,其中x和y是n维的输入值,f(·) 是从n ...
- linux系统mysql密码修改脚本
编写了一个适用于阿里云linux系统 mysql密码修改脚本,使用阿里云提供的一键安装包配置后,如果account.log文件删除,并且忘记mysql密码时,可以通过脚本来重置mysql密码. 附:一 ...