题目大意:

有一棵树,根节点为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. mongodb--安全

    安全和认证 mongodb和redis比较像,安全部分依赖于其所存在的环境 一定要把mongodb放在一个可信的环境下去运行,mongodb只能被web服务器所访问,禁止开外网端口访问mongodb, ...

  2. Linux用户管理之使用/bin/false和/usr/sbin/nologin拒绝用户登录及其功能分析(转)

    /bin/nologin,/bin/false的意思是禁止某个用户登录. 比较常用的用法: #添加一个不能登录的用户 useradd -d /usr/local/apache -g apache -s ...

  3. jplogic v1.0案例开发之知识库管理(文档管理等)(二)

    jplogic v1.0开发陆续更新,意在和广大网友分享交流.通过寻求合作伙伴,交流群.以下是jplogic的关于知识库模块的部分功能,例如以下进行功能展示: 知识库主界面: 新增知识类别: wate ...

  4. 50套html站点模板,涵盖非常多行业,各种类型html站点,各种行业html站点模板下载

    50套html站点模板,涵盖非常多行业,各种类型html站点.各种行业html站点模板下载 所以模板都在共享文件中面QQ群 139639813 ,快下载吧.

  5. 杭电(hdu)ACM 1010 Tempter of the Bone

    Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Othe ...

  6. hdu4762Cut the Cake(概率+大数操作(java)+C++高精度模板)

    题目链接:点击打开链接 题目描写叙述:现有一个大蛋糕.上面随机分布了n个草莓,然后将草莓切成m块,问n个草莓全在一块蛋糕上面的概率? 解题思路:细致分析可得:C(n,1)/m^(n-1) 因为m< ...

  7. jQuery高性能自己定义滚动栏美化插件

    malihu是一款高性能的滚动栏美化jQuery插件. 该滚动栏美化插件支持水平和垂直滚动栏,支持鼠标滚动,支持键盘滚动和支持移动触摸屏. 而且它能够和jQuery UI和Bootatrap完美的结合 ...

  8. Binding Enum to ComboBox

    1.添加MarkupExtension public class EnumToSourceExtension : MarkupExtension { private Type _type; publi ...

  9. hdu1829 A Bug&#39;s Life(并查集)

    开两个并查集.然后合并的时候要合并两次.这样在合并之前推断是否冲突,假设不冲突就进行合并,否则不须要继续合并. #include<cstdio> #include<cstdlib&g ...

  10. P4396 [AHOI2013]作业 分块+莫队

    这个题正解是莫队+树状数组,但是我个人非常不喜欢树状数组这种东西,所以决定用分块来水这个题.直接在莫队维护信息的时候,维护单点同时维护块内信息就行了. 莫队就是这几行核心代码: void add(in ...