题目大意:

有一棵树,根节点为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. 在java中,怎样跳出当前的多重循环?

    </pre>直接用break ;详细举比例如以下:<p></p><p></p><p></p><pre name ...

  2. Android下添加新的自定义键值和按键处理流程【转】

    本文转载自: Android下添加新的自定义键值和按键处理流程     说出来不怕大家笑话,我写这篇博客的原因在于前几天去一个小公司面试Android系统工程师,然后在面试的时候对方的技术总监问了我一 ...

  3. 0x57 倍增优化DP

    真的是下定了巨大的决心来搞这一讲,果不其然耗了一晚上 开车旅行(真的是NOIP的题吗怎么这么恐怖) 首先,先用set把小A和小B从城市i出发,到达的下一个城市预处理出来. f[i][j][k]表示走了 ...

  4. 网络 - TCP/IP四层模型,面向生产

    TCP.IP四层模型 (网络接口层,网际互联层,传输层,应用层.) (左边是车模,右边是实际生产的车.) 物理层,负责0101比特流传递. 数据链路层,MAC地址负责局域网,内网通信.MAC地址,由4 ...

  5. 框架-Java:Spring Cloud

    ylbtech-框架-Java:Spring Cloud Spring Cloud是一系列框架的有序集合.它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册. ...

  6. 最详细的CentOS 6与7对比(二):服务管理对比

    本主题将从3个角度进行对比 常见设置(CentOS 6 vs CentOS 7) 服务管理(Sysvinit vs Upstart vs Systemd) 性能测试(cpu/mem/io/oltp) ...

  7. Promise解决回调地狱

    Promise是JavaScript异步操作解决方案.介绍Promise之前,先对异步操作做一个详细介绍. JavaScript的异步执行 概述 Javascript语言的执行环境是”单线程”(sin ...

  8. SwiftUI 官方教程(三)

    3. 用 Stacks 组合 View 在上一节创建标题 view 后,我们来添加 text view,它用来显示地标的详细信息,比如公园的名称和所在的州. 在创建 SwiftUI view 时,我们 ...

  9. Arduino-IIC-Wire.h

    前言:Wire.h是Arduino的IIC库. 一.Wire库函数 Wire.begin() Wire.requestFrom() Wire.beginTransmission() Wire.endT ...

  10. POJ 1200 Hash

    我的hash从来没写对过........ (白学了快一年OI --原来连个hash都没写对过) 但是 但是 今天是一个值得纪念的日子. 看看标题 我竟然在写hash的题解. (好了好了 废话少说) 题 ...