题目大意:

有一棵树,根节点为1。每个点有点权。有两种操作。

1. 求节点x所在子树中点权与y异或的最大值。
2. 求x到y的路径上点权与z异或的最大值。

解题思路:

可持久化字典树。

对于第一种操作,我们对树进行dfs遍历,求出每个节点的dfs序(树剖),然后由于子树中dfs序连续,所以相当于区间的询问。对每个1~x区间建trie即可。

对于第二种操作,我们对每个节点建一颗trie,记录其到根的路径上的信息。

然后常规求LCA,减一减即可。

C++ Code:

#include<bits/stdc++.h>
const int N=1e5+5;
int ch[N<<6][2],siz[N<<6],ccnt=0,n,q,a[N],head[N],to[N<<1],nxt[N<<1];
int sz[N],dep[N],son[N],top[N],trie1[N],trie2[N],dfn[N],idfn[N],idx=0,fa[N],ans;
inline int readint(){
int c=getchar(),d=0;
for(;!isdigit(c);c=getchar());
for(;isdigit(c);c=getchar())
d=(d<<3)+(d<<1)+(c^'0');
return d;
}
void Insert(int&nw,int&o,int&p,int pp=30){
nw=++ccnt;
if(!~pp)return(void)(siz[nw]=siz[o]+1);
ch[nw][0]=ch[o][0];
ch[nw][1]=ch[o][1];
int nxt=(p>>pp)&1;
Insert(ch[nw][nxt],ch[o][nxt],p,pp-1);
siz[nw]=siz[ch[nw][0]]+siz[ch[nw][1]];
}
void dfs1(int now,int pre){
sz[now]=1;
Insert(trie1[now],trie1[pre],a[now]);
for(int i=head[now];i;i=nxt[i])
if(!dep[to[i]]){
dep[to[i]]=dep[now]+1;
fa[to[i]]=now;
dfs1(to[i],now);
sz[now]+=sz[to[i]];
if(!son[now]||sz[to[i]]>sz[son[now]])son[now]=to[i];
}
}
void dfs2(int now){
idfn[dfn[now]=++idx]=now;
if(son[now])top[son[now]]=top[now],dfs2(son[now]);
for(int i=head[now];i;i=nxt[i])
if(to[i]!=son[now]&&dep[to[i]]>dep[now])
dfs2(top[to[i]]=to[i]);
}
inline int LCA(int x,int y){
while(top[x]!=top[y])
if(dep[top[x]]>=dep[top[y]])x=fa[top[x]];else
y=fa[top[y]];
return dep[x]<dep[y]?x:y;
}
void query(int&R,int&L,int&num,int pp=30){
if(!~pp)return;
int nw=(num>>pp)&1^1;
if(siz[ch[R][nw]]>siz[ch[L][nw]]){
ans|=1<<pp;
query(ch[R][nw],ch[L][nw],num,pp-1);
}else
query(ch[R][!nw],ch[L][!nw],num,pp-1);
}
void query2(int&x,int&y,int&lca,int&fa,int&num,int pp=30){
if(!~pp)return;
int nw=(num>>pp)&1^1;
if(siz[ch[x][nw]]+siz[ch[y][nw]]-siz[ch[lca][nw]]-siz[ch[fa][nw]]>0){
ans|=1<<pp;
query2(ch[x][nw],ch[y][nw],ch[lca][nw],ch[fa][nw],num,pp-1);
}else
query2(ch[x][!nw],ch[y][!nw],ch[lca][!nw],ch[fa][!nw],num,pp-1);
}
int main(){
n=readint(),q=readint();
for(int i=1;i<=n;++i)a[i]=readint();
for(int i=1;i<n;++i){
int u=readint(),v=readint();
to[i<<1]=v;nxt[i<<1]=head[u];
head[u]=i<<1;
to[i<<1|1]=u;nxt[i<<1|1]=head[v];
head[v]=i<<1|1;
}
memset(dep,0,sizeof dep);
memset(son,0,sizeof son);
dep[1]=1;
dfs1(1,0);
dfs2(1);
for(int i=1;i<=n;++i)
Insert(trie2[i],trie2[i-1],a[idfn[i]]);
while(q--)
if(readint()==1){
int x=readint(),y=readint();
ans=0;query(trie2[dfn[x]+sz[x]-1],trie2[dfn[x]-1],y);
printf("%d\n",ans);
}else{
int x=readint(),y=readint(),z=readint();
int lca=LCA(x,y);
ans=0;
query2(trie1[x],trie1[y],trie1[lca],trie1[fa[lca]],z);
printf("%d\n",ans);
}
return 0;
}

  

[TJOI2018]xor的更多相关文章

  1. bzoj 5338: [TJOI2018]xor (树链剖分+可持久化01Trie)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=5338 题面: 5338: [TJOI2018]xor Time Limit: 30 Sec  ...

  2. BZOJ.5338.[TJOI2018]xor(可持久化Trie)

    BZOJ LOJ 洛谷 惊了,18年了还有省选出模板题吗= = 做这题就是练模板的,我就知道我忘的差不多了 询问一就用以DFS序为前缀得到的可持久化Trie做,询问二很经典的树上差分. 注意求询问二的 ...

  3. BZOJ5338[TJOI2018]xor——主席树+dfs序

    题目描述 现在有一颗以1为根节点的由n个节点组成的树,树上每个节点上都有一个权值vi. 现在有Q 次操作,操作如下: 1  x y    查询节点x的子树中与y异或结果的最大值 2 x y z     ...

  4. BZOJ5338 [TJOI2018] Xor 【可持久化Trie树】【dfs序】

    题目分析: 很无聊的一道题目.首先区间内单点对应异或值的询问容易想到trie树.由于题目在树上进行,case1将路径分成两段,然后dfs的时候顺便可持久化trie树做询问.case2维护dfs序,对d ...

  5. [BZOJ5338][TJOI2018]xor(可持久化Trie)

    可持久化Trie模板题. 建两种可持久化Trie,每个点两棵,一棵对DFS求前缀和,一棵对祖先求前缀和. 或者树剖,不好写多少还多个log. #include<cstdio> #inclu ...

  6. 可持久化trie(BZOJ5338: [TJOI2018]xor)

    题面 BZOJ Sol 显然是要维护一个区域的 \(trie\) 树,然后贪心 区间 \(trie\) 树??? 可持久化 \(trie\) 树??? 直接参考主席树表示出区间的方法建立 \(trie ...

  7. [BZOJ5338][TJOI2018]xor

    bzoj luogu descirption 现在有一棵以 \(1\) 为根节点的由 \(n\) 个节点组成的树,树上每个节点上都有一个权值 \(v_i\) .现在有 \(Q\) 次操作,操作如下: ...

  8. [TJOI2018] Xor 异或 (可持久化Trie,树链剖分)

    题目描述 现在有一颗以 1 为根节点的由 n 个节点组成的树,树上每个节点上都有一个权值 \(v_i\).现在有 Q 次操作,操作如下: 1 x y :查询节点 x 的子树中与 y 异或结果的最大值. ...

  9. BZOJ 5338: [TJOI2018]xor 可持久化trie+dfs序

    强行把序列问题放树上,好无聊啊~ code: #include <bits/stdc++.h> #define N 200005 #define setIO(s) freopen(s&qu ...

随机推荐

  1. DJANGO之自定义模板过滤器

    我查找了DJANGO模板的过滤器,好像指定字符串包含指定关-键字符的过滤器没有呢, 没有硬着头-皮,按网上其它人的作法,写了一个,成功了...:) 参考URL: http://liuzhijun.it ...

  2. codevs——T1169 传纸条

    http://codevs.cn/problem/1169/  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 De ...

  3. MySQL优化之——为用户开通mysql权限

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46627263 为用户开通mysql权限: grant all privileges ...

  4. 剖析Mysql的InnoDB索引

    摘要: 本篇介绍下Mysql的InnoDB索引相关知识,从各种树到索引原理到存储的细节. InnoDB是Mysql的默认存储引擎(Mysql5.5.5之前是MyISAM,文档).本着高效学习的目的,本 ...

  5. Linux shell脚本中shift的用法说明【转】

    本文转载自:http://blog.csdn.net/zhu_xun/article/details/24796235 Linux shell脚本中shift的用法说明 shift命令用于对参数的移动 ...

  6. 国外物联网平台初探(三) ——IBM Watson IoT

    平台定位 提供全面管理的云托管服务,旨在简化并从 IoT 设备中获得价值. Watson IoT Platform 提供对 IoT 设备和数据的强大应用程序访问,可快速编写分析应用程序.可视化仪表板和 ...

  7. docker overlay网络实现

    DOCKER的内置OVERLAY网络 内置跨主机的网络通信一直是Docker备受期待的功能,在1.9版本之前,社区中就已经有许多第三方的工具或方法尝试解决这个问题,例如Macvlan.Pipework ...

  8. kindoreditor上传图片

    <!doctype html><html> <head> <meta charset="utf-8" /> <title> ...

  9. js作业

    1.一张纸的厚度是0.0001米,将纸对折,对折多少次厚度超过珠峰高度8848米var sum=0;i=0;a=0.0001;for(i=0;i<100;i++){ a=a*2; sum=sum ...

  10. Polyfill 与 Shim

    Polyfill 与 Shim polyfill 的概念是 Remy Sharp 在2010年提出的. polyfill,或 polyfiller ,表示为开发人员提供旧浏览器没有原生支持的较新功能的 ...