[TJOI2018]xor
2024-08-27 07:29:17
题目大意:
有一棵树,根节点为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;
}
最新文章
- svn 合并分支代码到主干
- coursera机器学习笔记-机器学习概论,梯度下降法
- sql server 还原数据库时提示数据库正在使用,无法进行操作的解决方法
- POJ 2186 Popular Cows(强连通分量缩点)
- POJ 1017 Packets
- 解决 this virtual machine’s policies are too old to be run by this version of vmware workstation”
- AppDomain与进程、线程、Assembly之间关系
- C库函数笔记
- (二)boost库之字符串格式化
- JQuery-基础学习1
- C#读取Excel表格中数据并返回datatable
- ES6知识整理(1)--let和const命令
- IDEA项目的复制操作
- 9.26/27 blog项目
- eclipse 出现内存溢出问题解决办法
- 八大排序算法python实现
- php初中高阶段
- 浅析android应用增量升级(转)
- linux访问ftp服务器命令
- Tajo--一个分布式数据仓库系统(分布式环境安装试用)
热门文章
- SPOJ 1811LCS Longest Common Substring
- ArcEngine 地图导航 查找路径 经纬度坐标导航 最优路径分析
- fastjson null 值处理
- 基础树形DP小结
- udev的使用-minicom没有权限打开串口,更改 ttyUSB0 的权限
- Linux shell脚本中shift的用法说明【转】
- Code Coverage and Unit Test in SonarQube
- Dark roads--hdoj
- 前后端分离开发,基于SpringMVC符合Restful API风格Maven项目实战(附完整Demo)!
- 同一sql程序执行比数据库执行慢