HDU 4757 可持久化trie树
首先如果给定一些数,询问这些数中哪个数^给定的数的值最大的话,我们可以建立一颗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树的更多相关文章
- 可持久化Trie树初步
可持久化Trie树和可持久化线段树很像,依次插入信息,通过减法来进行历史版本查询. 2015年11月27日 bzoj3261 最大异或和 我们需要计算 a[p] xor a[p+1] xor ... ...
- [十二省联考2019]异或粽子——可持久化trie树+堆
题目链接: [十二省联考2019]异或粽子 求前$k$大异或区间,可以发现$k$比较小,我们考虑找出每个区间. 为了快速得到一个区间的异或和,将原序列做前缀异或和. 对于每个点作为右端点时,我们维护出 ...
- BZOJ4477[Jsoi2015]字符串树——可持久化trie树
题目描述 萌萌买了一颗字符串树的种子,春天种下去以后夏天就能长出一棵很大的字符串树.字符串树很奇特,树枝上都密密麻麻写满了字符串,看上去很复杂的样子.[问题描述]字符串树本质上还是一棵树,即N个节点N ...
- BZOJ5338 [TJOI2018] Xor 【可持久化Trie树】【dfs序】
题目分析: 很无聊的一道题目.首先区间内单点对应异或值的询问容易想到trie树.由于题目在树上进行,case1将路径分成两段,然后dfs的时候顺便可持久化trie树做询问.case2维护dfs序,对d ...
- 51nod 1295 XOR key (可持久化Trie树)
1295 XOR key 题目来源: HackerRank 基准时间限制:1.5 秒 空间限制:262144 KB 分值: 160 难度:6级算法题 给出一个长度为N的正整数数组A,再给出Q个查 ...
- 【BZOJ-4212】神牛的养成计划 Trie树 + 可持久化Trie树
4212: 神牛的养成计划 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 136 Solved: 27[Submit][Status][Discus ...
- 51nod 1295 XOR key | 可持久化Trie树
51nod 1295 XOR key 这也是很久以前就想做的一道板子题了--学了一点可持久化之后我终于会做这道题了! 给出一个长度为N的正整数数组A,再给出Q个查询,每个查询包括3个数,L, R, X ...
- 【bzoj2741】[FOTILE模拟赛]L 可持久化Trie树+分块
题目描述 FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor A ...
- bzoj 3261: 最大异或和 (可持久化trie树)
3261: 最大异或和 Time Limit: 10 Sec Memory Limit: 512 MB Description 给定一个非负整数序列 {a},初始长度为 N. ...
随机推荐
- lol人物模型提取(六)
模型昨天就已经做出来了,不过到上色这一块貌似又遇到了一些问题.由于模型的眼睛比较小,没法做出亮光效果,上不了UV,只能做哑光效果的. 亮光效果: 哑光效果: 很显然亮光效果更加好看一点 ...
- BZOJ2938 & 洛谷2444:[POI2000]病毒——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2938 https://www.luogu.org/problemnew/show/P2444 二进制 ...
- BZOJ2752:[HAOI2012]高速公路——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2752 https://www.luogu.org/problemnew/show/P2221#sub ...
- Nginx配置解析
#运行用户,默认即是nginx,可不设置 #user nobody; #nginx进程,一般设置为和cpu核数一样 worker_processes 1; #;单个后台worker process进程 ...
- 读取proc/uptime信息。
#include <stdio.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h ...
- tinyxml源码解析(上)
转载于:http://www.cnblogs.com/marchtea/archive/2012/11/09/2762669.html 前言: 前段时间做功能可行性的时候简单的使用了tinyxml.在 ...
- HDU 2852 主席树
KiKi's K-Number Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- Codeforces Round #493 (Div. 2)D. Roman Digits 第一道打表找规律题目
D. Roman Digits time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...
- qt4+vs2010 环境搭建
1.安装开发所需的软件: vs2010(包括VS2010SP1dvd1,Visual_Assist_X_10.9.2062.0_Crack等) QT: qt-win-opensource-4.8.5- ...
- 在Linux防火墙上过滤外来的ICMP timestamp
ICMP timestamp请求响应漏洞 解决方案: * 在您的防火墙上过滤外来的ICMP timestamp(类型13)报文以及外出的ICMP timestamp回复报文. 具体解决方式就 ...