题目链接

题目大意:有一颗树,有点权,每次询问:一条路径\(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. vue学习笔记一

    vue 颠覆式的开发方式 解疑 为什么要学习vue? 降低项目的复杂度 就业需要 vue难不难? 特别简单 相比于React,vue有什么优势? 前端三大框架:Angular.React.Vue Vu ...

  2. shell小技巧(4)AIX和Linux计算天前日期

    Linux计算天前日期: date -d "- day" +%Y%m%d AIX计算5天前日期: perl -e "use POSIX qw(strftime); pri ...

  3. 在MyBatis中采用模糊查询变量的引用标志应当是$而不是#

    具体如下例: @Select("select count(*) from hy_stock where name like '%${keyword}%' or code like '%${k ...

  4. 将微服务部署到 Azure Kubernetes 服务 (AKS) 实践

    本文是对 <.NET Tutorial - Deploy a microservice to Azure> 的翻译和实践.入门级踩坑实践,k8s 大佬请回避,以免耽误您宝贵的时间. 介绍 ...

  5. PHP开发规范1.3.3

    PHP 开发规范1.3.3 一.编程规约 (一) 命名风格 [强制]代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式. 说明: 正确的英文拼写和语法可以让阅读者易于理解,避免歧义. ...

  6. ASP.NET Core 3.x启动时运行异步任务(一)

    这是一个大的题目,需要用几篇文章来说清楚.这是第一篇.   一.前言 在我们的项目中,有时候我们需要在应用程序启动前执行一些一次性的逻辑.比方说:验证配置的正确性.填充缓存.或者运行数据库清理/迁移等 ...

  7. Dell服务器R710修改iDRAC密码

    此方法需重启,重启之前记住保存 重要数据,停止服务器相关服务.所以此操作最好在还未装系统前先设置好. 开机(重启)持续按CTRL+E进入iDRAC设置界面,选择意思为恢复默认的选项,风扇会非常的响,之 ...

  8. (专题一)03 matlab变量及其操作

    给内存单元取名字就可以访问内存单元 变量的命名:变量名区分大小写 标准函数名以及命名方式必须用小写字母 matlab赋值语句有两种表达式 变量的管理       1.预定义变量  ans 是默认赋值变 ...

  9. 利用Python爬取疫情数据并使用可视化工具展示

    import requests, json from pyecharts.charts import Map, Page, Pie, Bar from pyecharts import options ...

  10. Redis中String类型的相关命令操作

    String append 如果key已存在,则直接在value追加值,如果key不存在,则会插件一个新的value为空的key,然后在追加 127.0.0.1:6379> set name l ...