【题解】hdu4757 【TJOI2018】异或
题目大意:有一颗树,有点权,每次询问:一条路径\(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】异或的更多相关文章
- 【BZOJ5338】[TJOI2018]异或(主席树)
[BZOJ5338][TJOI2018]异或(主席树) 题面 洛谷 题解 很明显的是\(Trie\)树上暴力判断答案 因为要支持区间,用主席树的结构存\(Trie\)树就好了 #include< ...
- 洛谷 P4592 [TJOI2018]异或 解题报告
P4592 [TJOI2018]异或 题目描述 现在有一颗以\(1\)为根节点的由\(n\)个节点组成的树,树上每个节点上都有一个权值\(v_i\).现在有\(Q\)次操作,操作如下: 1 x y:查 ...
- BZOJ5338:[TJOI2018]异或——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5338 现在有一颗以1为根节点的由n个节点组成的树,树上每个节点上都有一个权值vi. 现在有Q 次操 ...
- 洛谷 P4592: bzoj 5338: [TJOI2018]异或
题目传送门:洛谷P4592. 题意简述: 题面说的很清楚了. 题解: 发现没有修改很快乐.再看异或最大值操作,很容易想到可持久化 01trie. 这里要把 01trie 搬到树上,有点难受. 树剖太捞 ...
- [洛谷P4592][TJOI2018]异或
题目大意:有一棵$n$个点的树,第$i$个点权值为$w_i$,有两种操作: $1\;x\;y:$询问节点$x$的子树中与$y$异或结果的最大值 $2\;x\;y\;z:$询问路径$x$到$y$上点与$ ...
- P4592 [TJOI2018]异或 (可持久化Trie)
[题目链接] https://www.luogu.org/problemnew/show/P4592 题目描述 现在有一颗以\(1\)为根节点的由\(n\)个节点组成的树,树上每个节点上都有一个权值\ ...
- 【题解】kth异或和/魔改版线性基
[题解]魔改版线性基 魔改版线性基解决此类问题. 联系线性空间的性质,我们直接可以构造出这样的基: \[ 100000 \\ 010000 \\ 000010 \\ 000001 \] 使得每个基的最 ...
- [TJOI2018]异或
Description: 现在有一颗以1为根节点的由n个节点组成的树,树上每个节点上都有一个权值v 现在有Q次操作,操作如下: 1.1 x y :查询节点x的子树中与y异或结果的最大值 2.2 x ...
- 可持久化01Trie树+LCA【p4592】[TJOI2018]异或
Description 现在有一颗以\(1\)为根节点的由\(n\)个节点组成的树,树上每个节点上都有一个权值\(v_i\).现在有\(Q\)次操作,操作如下: 1\(\;x\;y\):查询节点\(x ...
- 洛谷P4592 [TJOI2018]异或 【可持久化trie树】
题目链接 BZOJ4592 题解 可持久化trie树裸题 写完就A了 #include<algorithm> #include<iostream> #include<cs ...
随机推荐
- Vue.js学习(八)—— 树形结构下拉框组件vue-treeselect
vue-treeselect是一个多选组件,具有对Vue.js的嵌套选项支持. 具有嵌套选项支持的单个和多个选择 模糊匹配 异步搜索 延迟加载(仅在需要时加载深层选项的数据) 键盘支持(使用Arrow ...
- 我对Flutter的第一次失望
老孟导读:此文翻译自:https://medium.com/@suragch/my-first-disappointment-with-flutter-5f6967ba78bf 我喜欢Flutter. ...
- wxmini
微信小游戏架构概览 https://www.jianshu.com/p/02199c35d749 微信小程序:工具配置 project.config.json https://www.cnblogs. ...
- CA定义以及功能说明
当您访问以HTTPS开头的网站时,即表示正在使用CA.CA是Internet的重要组成部分.如果不存在CA,那么将无法安全在线购物以及使用网银在线业务等.什么是CA?CA具体是做什么的,又是如何确保您 ...
- Guava Retrying
目录 依赖 使用demo RetryerBuilder 实现callable接口 调用 git 参考 依赖 <dependency> <groupId>com.github.r ...
- Jwt快速入门(copy即可)
Jwt 什么是jwt JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案,本文介绍它的原理和用法. 互联网服务离不开用户认证.一般流程是下面这样. 1.用户向服务器发送用户名和 ...
- linux 增加新用户无法使用sudo命令解决办法
昨天一不小心把自己的系统搞崩了,也没有快照,没法进行还原操作,所以只能重装系统解决了,装完系统以后一切正常,当我新增了一个用户,使用sudo命令切换到root用户时,发现怎么都切换不过去,经过百度发现 ...
- leetcode刷题-58最后一个单词
题目 给定一个仅包含大小写字母和空格 ' ' 的字符串 s,返回其最后一个单词的长度.如果字符串从左向右滚动显示,那么最后一个单词就是最后出现的单词. 如果不存在最后一个单词,请返回 0 . 说明:一 ...
- appium 基础二:常用api接口
一.获取手机分辨率 size=driver.get_window_size()#获取手机屏幕大小,分辨率 print(size)#{'width': 720, 'height': 1280} 得到的是 ...
- list列表(也叫数组),以及常用的一些方法
列表的表达: 元祖tuple,元祖是不可被修改的列表 1.列表的增,list.append(元素).或list.insert(index,元素) 2.列表的删,list.pop(可指定index也可不 ...