【题解】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 ...
随机推荐
- 深圳做假证h
深圳做假证[电/薇:187ヘ1184ヘ0909同号]办各类证件-办毕业证-办离婚证,办学位证书,办硕士毕业证,办理文凭学历,办资格证,办房产证不. 这是一个简单的取最大值程序,可以用于处理 i32 数 ...
- sort(桶排序+hash)
题目链接:https://cn.vjudge.net/problem/HDU-1425 注意是多组输入 代码: #include<cstdio> #include<iostream& ...
- GitHub 热点速览 Vol.36:当股票遇到机器学习,异常股无所遁形
作者:HelloGitHub-小鱼干 摘要:虽然上周的 GitHub Trending 榜新项目寥寥无几,但胜在表现不俗,例如:通过机器学习来检测异常股票的项目 Surpriver,还有腾讯开源的管理 ...
- zt:HttpUrlConnection使用详解
下文转载自:https://www.cnblogs.com/tenWood/p/8563617.html 一,HttpURLconnection的介绍 在Android开发中网络请求是最常用的操作之一 ...
- PHP复杂变量
eval($str="${${phpinfo()}}";) → 可以执行phpinfo() ${phpinfo()} = {${phpindo()}} PHP复杂变量 ...
- C#中部分重点前端设置问题
背景 在工作及学习过程中经常会遇到一些奇怪的需求,这里便会记录我遇到的奇怪需求及解决方法. 内容 一.动态设置页面标题 1.前端设置 JS代码: document.title="这是一个标题 ...
- parseQueryString
var parseQueryString = function (url) { var reg = /([^\?\=\&]+)\=([^\?\=\&]*)/g; var o ...
- 面试:为了进阿里,重新翻阅了Volatile与Synchronized
该系列文章收录在公众号[Ccww技术博客],原创技术文章早于博客推出 在深入理解使用Volatile与Synchronized时,应该先理解明白Java内存模型 (Java Memory Model, ...
- Linux下 ls 命令的高级用法8例
Linux下 ls 命令的高级用法8例 在Linux下,ls这个命令大家肯定太熟悉了,良许相信只要是Linux工程师,每天都会离不开这个命令,而且一天会使用个几百次.但是,除了 ls -l 以外,你还 ...
- 如何把Github上好的项目pull到本地或者fork到本地(码云仓库同理)?
首先Github账户的注册我就不想再啰嗦了,我想大家都会的. 其次怎么把自己的项目push到自己的Github仓库请参考我的另一篇博客: 如何把自己开发的项目上传到GitHub仓库或者码云仓库? 最后 ...