题目链接

题目大意:有一颗树,有点权,每次询问:一条路径\(x->y\)中与\(z\)异或的最大值,或是以\(x\)为根的子树中与\(y\)异或的最大值。

树剖……还是算了。

观察到,子树的\(dfn\)序是连续的一段区间。于是我们可以预处理\(dfs\)序来解决这个问题。

第二问,我们可以求两点的最近公共祖先,做一个树上差分来实现。

维护两颗可持久化\(Trie.\)一个维护\(dfs\)序,一个维护\(x->root\).

当然\(HDU\)的那个题是没有第一个操作的,但是是多组询问。

\(HDU:\)

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+10;
int n,m,siz[MAXN],dfn[MAXN],f[MAXN][25];
int dep[MAXN],head[MAXN<<1],tot,dfstime;
int pre[MAXN],a[MAXN];
struct edge{
int nxt,to;
}e[MAXN<<1];
inline void add(int x,int y){
e[++tot].to=y;
e[tot].nxt=head[x];
head[x]=tot;
}
struct Trie{
int son[MAXN<<5][2],ct[MAXN<<5],root[MAXN],cnt=1;
void Insert(int &rt,int x,int T){
ct[++cnt]=ct[rt]+1;
son[cnt][0]=son[rt][0];
son[cnt][1]=son[rt][1];
rt=cnt;
if(T==-1)return;
bool y=(x>>T)&1;
Insert(son[rt][y],x,T-1);
}
void Ins(int pre,int rt,int x){
root[rt]=root[pre];
Insert(root[rt],x,30);
}
int Q(int i,int j,int x,int T){
if(T==-1)return 0;
int y=(x>>T)&1;
if(ct[son[j][1^y]]>ct[son[i][1^y]])return ((1<<T)+Q(son[i][1^y],son[j][1^y],x,T-1));
return Q(son[i][y],son[j][y],x,T-1);
}
int QT(int i,int j,int lc,int flc,int x,int T){
if(T==-1)return 0;
int y=(x>>T)&1;
if(ct[son[i][1^y]]+ct[son[j][1^y]]>ct[son[lc][1^y]]+ct[son[flc][1^y]])return ((1<<T)+QT(son[i][1^y],son[j][1^y],son[lc][1^y],son[flc][1^y],x,T-1));
else return QT(son[i][y],son[j][y],son[lc][y],son[flc][y],x,T-1);
}
int query(int i,int j,int x){
return Q(root[i-1],root[j],x,30);
}
int UQT(int i,int j,int lc,int flc,int x){
return QT(root[i],root[j],root[lc],root[flc],x,30);
}
void clear(){
cnt=1;
memset(root,0,sizeof(root));
memset(ct,0,sizeof(ct));
memset(son,0,sizeof(son));
}
}tr1;
void dfs(int u,int fa){
dep[u]=dep[fa]+1;siz[u]=1;
pre[dfn[u]=++dfstime]=u;
f[u][0]=fa;
for(int i=1;i<=22;++i)f[u][i]=f[f[u][i-1]][i-1];
tr1.Ins(fa,u,a[u]);
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==fa)continue;
dfs(v,u);siz[u]+=siz[v];
}
}
int LCA(int u,int v){
if(dep[u]<dep[v])u^=v^=u^=v;
for(int i=22;i>=0;--i)
if(dep[f[u][i]]>=dep[v])u=f[u][i];
if(u==v)return u;
for(int i=22;i>=0;--i)
if(f[u][i]!=f[v][i])
u=f[u][i],v=f[v][i];
return f[u][0];
}
void work(){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
int A=LCA(x,y);
printf("%d\n",tr1.UQT(x,y,A,f[A][0],z));
}
int main(){
while(~scanf("%d%d",&n,&m)){
for(int i=1;i<=n;++i)scanf("%d",&a[i]);
for(int i=1;i<n;++i){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
dfs(1,0);
for(;m;m--)work();
memset(a,0,sizeof(a));
dfstime=0;tot=0;
memset(dfn,0,sizeof(dfn));
memset(pre,0,sizeof(pre));
memset(dep,0,sizeof(dep));
memset(siz,0,sizeof(siz));
memset(f,0,sizeof(f));
memset(head,0,sizeof(head));
tr1.clear();
} return 0;
}

\(Luogu:\)

#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+10;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')w=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
s=(s<<1)+(s<<3)+(ch^48);
ch=getchar();
}
return w==-1?-s:s;
}
int n,m,dep[MAXN],a[MAXN],siz[MAXN],dfn[MAXN];
int tot,ktot,head[MAXN<<1],pre[MAXN],f[MAXN][25];
struct edge{
int nxt,to;
}e[MAXN<<1];
inline void add(int x,int y){
e[++tot].to=y;
e[tot].nxt=head[x];
head[x]=tot;
}
struct Trie{
int son[MAXN<<5][2],cnt=1,root[MAXN],ct[MAXN<<5];
void Insert(int &rt,int x,int T){
ct[++cnt]=ct[rt]+1,son[cnt][0]=son[rt][0];
son[cnt][1]=son[rt][1];rt=cnt;
if(T==-1)return;
bool y=(x>>T)&1;
Insert(son[rt][y],x,T-1);
}
inline void Ins(int pre,int rt,int x){
root[rt]=root[pre];
Insert(root[rt],x,30);
}
int Q(int i,int j,int x,int T){
if(T==-1)return 0;
bool y=(x>>T)&1;
if(ct[son[j][1^y]]>ct[son[i][1^y]])return ((1<<T)+Q(son[i][1^y],son[j][1^y],x,T-1));
return Q(son[i][y],son[j][y],x,T-1);
}
int QT(int i,int j,int lc,int flc,int x,int T){
if(T==-1)return 0;
bool y=(x>>T)&1;
if(ct[son[j][1^y]]+ct[son[i][1^y]]>ct[son[lc][1^y]]+ct[son[flc][1^y]])return ((1<<T)+QT(son[i][1^y],son[j][1^y],son[lc][1^y],son[flc][1^y],x,T-1));
else return QT(son[i][y],son[j][y],son[lc][y],son[flc][y],x,T-1);
}
int query(int l,int r,int x){return Q(root[l-1],root[r],x,30);}
int UQT(int i,int j,int lc,int flc,int x,int T){
return QT(root[i],root[j],root[lc],root[flc],x,T);
}
}tr1,tr2;
void dfs(int u,int fa){
dep[u]=dep[fa]+1;f[u][0]=fa;
dfn[u]=++ktot;pre[ktot]=u;
tr1.Ins(fa,u,a[u]);siz[u]=1;
for(int i=1;i<=22;++i)f[u][i]=f[f[u][i-1]][i-1];
for(int i=head[u];i;i=e[i].nxt){
int j=e[i].to;
if(j==fa)continue;
dfs(j,u);siz[u]+=siz[j];
}
}
int LCA(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int i=22;i>=0;--i)
if(dep[f[x][i]]>=dep[y])x=f[x][i];
if(x==y)return x;
for(int i=22;i>=0;--i)
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][0];
} int main(){
n=read(),m=read();
for(int i=1;i<=n;++i)a[i]=read();
for(int i=1;i<n;++i){
int u=read(),v=read();
add(u,v);add(v,u);
}
dfs(1,0);
for(int i=1;i<=n;++i)tr2.Ins(i-1,i,a[pre[i]]);
for(;m;--m){
int opt=read();
if(opt==1){
int x=read(),y=read();
printf("%d\n",tr2.query(dfn[x],dfn[x]+siz[x]-1,y));
}
else {
int x=read(),y=read(),z=read(),A=LCA(x,y);
printf("%d\n",tr1.UQT(x,y,A,f[A][0],z,30));
}
}
return 0;
}

【题解】hdu4757 【TJOI2018】异或的更多相关文章

  1. 【BZOJ5338】[TJOI2018]异或(主席树)

    [BZOJ5338][TJOI2018]异或(主席树) 题面 洛谷 题解 很明显的是\(Trie\)树上暴力判断答案 因为要支持区间,用主席树的结构存\(Trie\)树就好了 #include< ...

  2. 洛谷 P4592 [TJOI2018]异或 解题报告

    P4592 [TJOI2018]异或 题目描述 现在有一颗以\(1\)为根节点的由\(n\)个节点组成的树,树上每个节点上都有一个权值\(v_i\).现在有\(Q\)次操作,操作如下: 1 x y:查 ...

  3. BZOJ5338:[TJOI2018]异或——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=5338 现在有一颗以1为根节点的由n个节点组成的树,树上每个节点上都有一个权值vi. 现在有Q 次操 ...

  4. 洛谷 P4592: bzoj 5338: [TJOI2018]异或

    题目传送门:洛谷P4592. 题意简述: 题面说的很清楚了. 题解: 发现没有修改很快乐.再看异或最大值操作,很容易想到可持久化 01trie. 这里要把 01trie 搬到树上,有点难受. 树剖太捞 ...

  5. [洛谷P4592][TJOI2018]异或

    题目大意:有一棵$n$个点的树,第$i$个点权值为$w_i$,有两种操作: $1\;x\;y:$询问节点$x$的子树中与$y$异或结果的最大值 $2\;x\;y\;z:$询问路径$x$到$y$上点与$ ...

  6. P4592 [TJOI2018]异或 (可持久化Trie)

    [题目链接] https://www.luogu.org/problemnew/show/P4592 题目描述 现在有一颗以\(1\)为根节点的由\(n\)个节点组成的树,树上每个节点上都有一个权值\ ...

  7. 【题解】kth异或和/魔改版线性基

    [题解]魔改版线性基 魔改版线性基解决此类问题. 联系线性空间的性质,我们直接可以构造出这样的基: \[ 100000 \\ 010000 \\ 000010 \\ 000001 \] 使得每个基的最 ...

  8. [TJOI2018]异或

    Description: 现在有一颗以1为根节点的由n个节点组成的树,树上每个节点上都有一个权值v ​现在有Q次操作,操作如下: 1.1 x y :查询节点x的子树中与y异或结果的最大值 2.2 x  ...

  9. 可持久化01Trie树+LCA【p4592】[TJOI2018]异或

    Description 现在有一颗以\(1\)为根节点的由\(n\)个节点组成的树,树上每个节点上都有一个权值\(v_i\).现在有\(Q\)次操作,操作如下: 1\(\;x\;y\):查询节点\(x ...

  10. 洛谷P4592 [TJOI2018]异或 【可持久化trie树】

    题目链接 BZOJ4592 题解 可持久化trie树裸题 写完就A了 #include<algorithm> #include<iostream> #include<cs ...

随机推荐

  1. WPF实现的加载动画

    2020-09-03 09:43:30 xaml代码 <Grid x:Name="LayoutRoot" Background="Transparent" ...

  2. app转iap

    ios打包ipa的四种实用方法(.app转.ipa) http://blog.csdn.net/oiken/article/details/49535369 手动压缩改后缀方式 这种方式与4.1的方法 ...

  3. 14 el-dialog 基本结构

    1 dialogVisible父组件提供,:visible.sync直接修改父组件的dialogVisible,会报错,需要加上before-close属性 <template> < ...

  4. Zookeeper协议篇-Paxos算法与ZAB协议

    前言 可以自行去学习一下Zookeeper中的系统模型,节点特性,权限认证以及事件通知Watcher机制相关知识,本篇主要学习Zookeeper一致性算法和满足分布式协调的Zab协议 Paxos算法 ...

  5. PHP生成二维码 endroid/qr-code 扩展包

    目录 1. 引入 endroid/qr-code 扩展包 2. 使用示例 3. 二维码中放入logo,无法识别二维码的问题 1. 引入 endroid/qr-code 扩展包 https://pack ...

  6. TP6.0中的密码验证逻辑、验证器的使用

    目录 1. 场景一:只有一个密码框,并且是可选项,留空不修改密码,不留空则修改密码 2. 场景二:两个密码框,修改密码时有新密码.确认密码,新密码框不为空时,确认密码才验证 1. 场景一:只有一个密码 ...

  7. Ubuntu修改默认Python版本,你了解多少~

    目录 1 查看Python版本 1.1 查看装有哪些版本 1.2 查看默认版本 2 修改Python默认版本 2.1 基于文件修改 2.2 基于软链接修改 1 查看Python版本 1.1 查看装有哪 ...

  8. 【吴恩达课程使用】keras cpu版安装【接】- anaconda (python 3.7) win10安装 tensorflow 1.8 cpu版

    一.确认tensorflow的版本: 接上一条tensorflow的安装,注意版本不匹配会出现很多问题!:[吴恩达课程使用]anaconda (python 3.7) win10安装 tensorfl ...

  9. JS中对获取一个标签的class的方法封一个库

    在JS中我们经常会会用到,获取一个标签的id var aId=document.getElementById("id") 现在虽然有getElementsByClassName这个 ...

  10. Shell编程(4)

    shell函数 shell中允许将一组命令集合或语句形成一段可用代码,这些代码块称为shell函数.给这段代码起个名字称为函数名,后续可以直接调用该段代码. 格式 func() { #指定函数名 co ...