HDU - 6191 Query on A Tree (可持久化字典树/字典树合并)
题意:有一棵树,树根为1,树上的每个结点都有一个数字x。给出Q组询问,每组询问有两个值u,x,代表询问以结点u为根的子树中的某一个数与x的最大异或值。
解法一:dfs序+可持久化字典树。看到子树询问,首先要想到dfs序啦。可以对所有结点按dfs序依次建立可持久化的字典树,字典树上的每个结点除了要保存它的后继结点以外,还要保存这个结点出现的次数num。询问结点u时,对[bg[u],ed[u]]上的字典树的num做差,字典树上剩下的num>0的结点即为可行状态,然后按普通的字典树的查询方法查询就是了。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+;
const int M=;
int n,Q,head[N],nxt[N],to[N],val[N],nEdge;
int rt[N],num[N*],go[N*][],nnode;
int bg[N],ed[N],tot;
void AddEdge(int u,int v) {
nxt[nEdge]=head[u],to[nEdge]=v,head[u]=nEdge++;
} int update(int v,int x,int bit) {
int u=++nnode;
num[u]=num[v]+;
if(bit<)return u;
int t=(x>>bit)&;
go[u][t]=update(go[v][t],x,bit-);
go[u][t^]=go[v][t^];
return u;
} void dfs(int u) {
bg[u]=++tot;
rt[tot]=update(rt[tot-],val[u],M);
for(int e=head[u]; ~e; e=nxt[e]) {
int v=to[e];
dfs(v);
}
ed[u]=tot;
} int query(int u,int v,int x,int bit,int now) {
if(bit<)return now;
int t=(x>>bit)&;
if(go[u][t^]-go[v][t^]>)
return query(go[u][t^],go[v][t^],x,bit-,now|(<<bit));
else return query(go[u][t],go[v][t],x,bit-,now);
} int main() {
while(scanf("%d%d",&n,&Q)==) {
memset(head,-,sizeof head);
nEdge=nnode=tot=;
for(int i=; i<=n; ++i)scanf("%d",&val[i]);
for(int i=; i<=n; ++i) {
int u;
scanf("%d",&u);
AddEdge(u,i);
}
rt[]=go[][]=go[][]=num[]=;
dfs();
while(Q--) {
int u,x;
scanf("%d%d",&u,&x);
printf("%d\n",query(rt[ed[u]],rt[bg[u]-],x,M,));
}
}
return ;
}
解法二:离线+字典树合并。可以自底而上来回答询问,每回答完一个结点下的所有子节点的询问,就将这个结点的字典树与它所有子节点的字典树合并。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+;
const int M=;
int n,Q,head[N],nxt[N],to[N],val[N],nEdge;
int rt[N],go[N*][],nnode,ans[N];
struct QUERY {
int x,i;
};
vector<QUERY> qr[N];
void AddEdge(int u,int v) {
nxt[nEdge]=head[u],to[nEdge]=v,head[u]=nEdge++;
} int build(int x,int bit) {
int u=++nnode;
if(bit<)return u;
int t=(x>>bit)&;
go[u][t]=build(x,bit-);
go[u][t^]=;
return u;
} int Merge(int u,int v,int bit) {
if(!u)return v;
if(!v)return u;
if(bit<)return u;
go[u][]=Merge(go[u][],go[v][],bit-);
go[u][]=Merge(go[u][],go[v][],bit-);
return u;
} int query(int u,int x,int bit,int now) {
if(bit<)return now;
int t=(x>>bit)&;
if(go[u][t^])
return query(go[u][t^],x,bit-,now|(<<bit));
else return query(go[u][t],x,bit-,now);
} void dfs(int u) {
for(int e=head[u]; ~e; e=nxt[e]) {
int v=to[e];
dfs(v);
}
for(int e=head[u]; ~e; e=nxt[e]) {
int v=to[e];
rt[u]=Merge(rt[u],rt[v],M);
}
for(int i=; i<qr[u].size(); ++i) {
ans[qr[u][i].i]=query(rt[u],qr[u][i].x,M,);
}
} int main() {
while(scanf("%d%d",&n,&Q)==) {
memset(head,-,sizeof head);
nEdge=nnode=;
for(int i=; i<=n; ++i)qr[i].clear();
for(int i=; i<=n; ++i)scanf("%d",&val[i]);
for(int i=; i<=n; ++i) {
int u;
scanf("%d",&u);
AddEdge(u,i);
}
for(int i=; i<=n; ++i)rt[i]=build(val[i],M);
for(int i=; i<Q; ++i) {
int u,x;
scanf("%d%d",&u,&x);
qr[u].push_back({x,i});
}
dfs();
for(int i=; i<Q; ++i)printf("%d\n",ans[i]);
}
return ;
}
还有一种解法是“可持久化字典树合并”,即父结点继承所有子结点的字典树,继承的方式与字典树合并一样,只不过把两棵树的公共部分开新结点就好,也是在线的,但空间消耗较大。
#define FRER() freopen("i.txt","r",stdin)
#define FREW() freopen("o.txt","w",stdout)
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+;
const int M=;
int n,Q,head[N],nxt[N],to[N],val[N],nEdge;
int rt[N],go[N*][],nnode,ans[N];
void AddEdge(int u,int v) {
nxt[nEdge]=head[u],to[nEdge]=v,head[u]=nEdge++;
}
int build(int x,int bit) {
int u=++nnode;
if(bit<)return u;
int t=(x>>bit)&;
go[u][t]=build(x,bit-);
go[u][t^]=;
return u;
}
int Merge(int u,int v,int bit) {
if(!u)return v;
if(!v)return u;
if(bit<)return u;
int w=++nnode;
go[w][]=Merge(go[u][],go[v][],bit-);
go[w][]=Merge(go[u][],go[v][],bit-);
return w;
}
int query(int u,int x,int bit,int now) {
if(bit<)return now;
int t=(x>>bit)&;
if(go[u][t^])
return query(go[u][t^],x,bit-,now|(<<bit));
else return query(go[u][t],x,bit-,now);
}
void dfs(int u) {
for(int e=head[u]; ~e; e=nxt[e]) {
int v=to[e];
dfs(v);
}
for(int e=head[u]; ~e; e=nxt[e]) {
int v=to[e];
rt[u]=Merge(rt[u],rt[v],M);
}
}
int main() {
while(scanf("%d%d",&n,&Q)==) {
memset(head,-,sizeof head);
nEdge=nnode=;
for(int i=; i<=n; ++i)scanf("%d",&val[i]);
for(int i=; i<=n; ++i) {
int u;
scanf("%d",&u);
AddEdge(u,i);
}
for(int i=; i<=n; ++i)rt[i]=build(val[i],M);
dfs();
for(int i=; i<Q; ++i) {
int u,x;
scanf("%d%d",&u,&x);
printf("%d\n",query(rt[u],x,M,));
}
}
return ;
}
HDU - 6191 Query on A Tree (可持久化字典树/字典树合并)的更多相关文章
- HDU 6191 Query on A Tree(可持久化Trie+DFS序)
Query on A Tree Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Othe ...
- HDU 6191 Query on A Tree(可持久化Trie)
题意 \(n\) 个点的有根树,根为 \(1\) .每个点有点权,有 \(q\) 个询问,每次询问以 \(u\) 为根的子树的点的点权中异或 \(x\) 所得的最大值是多少. 思路 求出整棵树的 \( ...
- [hdu 6191] Query on A Tree
Query on A Tree Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Othe ...
- HDU 6191 Query on A Tree(字典树+离线)
Query on A Tree Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Othe ...
- HDU 6191 Query on A Tree ( 2017广西邀请赛 && 可持久化Trie )
题目链接 题意 : 给你一棵树.树上的每个点都有点权.之后有若干次问询.每次问询给出一个节点编号以及一个整数 X .问你以给出节点为根的子树中哪个节点和 X 异或最大.输出这个值 分析 : 看到这种树 ...
- HDU 6191 2017ACM/ICPC广西邀请赛 J Query on A Tree 可持久化01字典树+dfs序
题意 给一颗\(n\)个节点的带点权的树,以\(1\)为根节点,\(q\)次询问,每次询问给出2个数\(u\),\(x\),求\(u\)的子树中的点上的值与\(x\)异或的值最大为多少 分析 先dfs ...
- HDU 4836 The Query on the Tree lca || 欧拉序列 || 动态树
lca的做法还是非常明显的.简单粗暴, 只是不是正解.假设树是长链就会跪,直接变成O(n).. 最后跑的也挺快,出题人还是挺阳光的.. 动态树的解法也是听别人说能ac的.预计就是放在splay上剖分一 ...
- QTREE3 spoj 2798. Query on a tree again! 树链剖分+线段树
Query on a tree again! 给出一棵树,树节点的颜色初始时为白色,有两种操作: 0.把节点x的颜色置反(黑变白,白变黑). 1.询问节点1到节点x的路径上第一个黑色节点的编号. 分析 ...
- HDU 4757 Tree 可持久化字典树 trie
http://acm.hdu.edu.cn/showproblem.php?pid=4757 给出一棵树,每个节点有权值,每次查询节点 (u,v) 以及 val,问 u 到 v 路径上的某个节点与 v ...
随机推荐
- Windows&Linux常用命令笔记
目录 linux windows Linux: 1.查找文件 find / -name filename.txt 根据名称查找/目录下的filename.txt文件. find . -name &qu ...
- iOS copy 和 mutableCopy 学习
(参考 iOS 52个技巧学习心得笔记 第二章 对象 , 消息, 运行期)的对象部分 关于Copy 有个经典问题”大部分的时候NSString的属性都是copy,那copy与strong的情况下到底 ...
- vue 数据传递的方法
组件(Component)是 Vue.js 最强大的功能.组件可以封装可重用的代码,通过传入对象的不同,实现组件的复用,但组件传值就成为一个需要解决的问题. 1.父组件向子组件传值 组件实例的作用域是 ...
- IPU VPU GPU的关系
转:https://blog.csdn.net/dragon101788/article/details/78404669 Video graphics system[IPU, VPU and GPU ...
- INSPIRED启示录 读书笔记 - 第20章 基本产品
消减功能还是延长工期 不要再试图定义最终产品,转而定义只满足基本要求的产品,简称基本产品 1.产品经理与设计师合作设计产品的高保真原型,这个原型只具备实现商业目标的最基本功能要求,以及良好的用户体验和 ...
- java基础之常量与变量
概要:通过这段时间的工作,发现自己的基础还是很薄弱的,so,you know 常量 一种特殊的变量,程序运行过程中不能改变的值 语法格式:final 数据类型 常量名称 = 常量值 例子:fina i ...
- RazorEngine性能研究(反射的延深)
先说下结论 1)RazorEngine 确实很慢,编译过程特别慢,编译过后仍不适合大量重复调用的情况(一次调用可以接受). 2 ) RazorEngine 和 asp.net mvc 里的Razo ...
- matlab第一个小应用
今天安装了matlab,以前还是上线性代数的时候,老师让用过,以及水了一次数模的时候玩了一下.以前太年轻,总觉得这个用处不大虽然别人一直强调这个神器... 到了自己要用的时候才会意识到.大家可能也都听 ...
- JAVA获取Spring上下文
1. 添加监听 public class SpringContextListener implements ServletContextListener { //获取spring注入的bean对象 p ...
- CocoaPods安装使用
$ gem sources --remove https://rubygems.org/ //等有反应之后再敲入以下命令 $ gem sources -a http://ruby.taobao.org ...