Description:

现在有一颗以1为根节点的由n个节点组成的树,树上每个节点上都有一个权值v

​现在有Q次操作,操作如下:

1.1\ x\ y\ :查询节点x的子树中与y异或结果的最大值

2.2\ x\ y\ z\ :查询路径x到y上点与z异或结果最大值

Hint:

\(n,q<=10^5\)

Solution:

水题,按dfs序建主席树解决询问1,树上主席树解决询问2

#include<bits/stdc++.h>
using namespace std;
const int mxm=1e5+5,mxn=5e6+5;
int n,m,cnt,val[mxm],hd[mxm],sz[mxm],id[mxm],dep[mxm],f[mxm][18]; struct ed {
int to,nxt;
}t[mxm<<1]; inline void add(int u,int v) {
t[++cnt]=(ed) {v,hd[u]}, hd[u]=cnt;
} struct Trie {
int ch[mxn][2],rt[mxn],sum[mxn],tot,dfn;
void dfs1(int u,int fa) {
sz[u]=1; id[u]=++dfn;
ins(rt[id[u]-1],rt[id[u]],30,val[u]);
for(int i=hd[u];i;i=t[i].nxt) {
int v=t[i].to;
if(v==fa) continue ;
dfs1(v,u); sz[u]+=sz[v];
}
}
void dfs2(int u,int fa) {
f[u][0]=fa; dep[u]=dep[fa]+1;
ins(rt[fa],rt[u],30,val[u]);
for(int i=hd[u];i;i=t[i].nxt) {
int v=t[i].to;
if(v==fa) continue ;
dfs2(v,u);
}
}
int LCA(int x,int y) {
if(dep[x]<dep[y]) swap(x,y);
for(int i=17;i>=0;--i)
if(dep[f[x][i]]>=dep[y])
x=f[x][i];
if(x==y) return x;
for(int i=17;i>=0;--i)
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][0];
}
void init() {
for(int j=1;j<=17;++j)
for(int i=1;i<=n;++i)
f[i][j]=f[f[i][j-1]][j-1];
}
void ins(int pre,int& p,int k,int x) {
p=++tot; sum[p]=sum[pre]+1; if(k<0) return ;
int tp=x>>k&1; ch[p][tp^1]=ch[pre][tp^1];
ins(ch[pre][tp],ch[p][tp],k-1,x);
};
int query1(int pre,int p,int k,int x) {
if(k<0) return 0; int tp=x>>k&1;
int is=sum[ch[p][tp^1]]-sum[ch[pre][tp^1]];
if(is) return (1<<k)+query1(ch[pre][tp^1],ch[p][tp^1],k-1,x);
else return query1(ch[pre][tp],ch[p][tp],k-1,x);
};
int query2(int las1,int las2,int p1,int p2,int k,int x) {
if(k<0) return 0; int tp=x>>k&1;
int is=sum[ch[p1][tp^1]]+sum[ch[p2][tp^1]]-sum[ch[las1][tp^1]]-sum[ch[las2][tp^1]];
if(is) return (1<<k)+query2(ch[las1][tp^1],ch[las2][tp^1],ch[p1][tp^1],ch[p2][tp^1],k-1,x);
else return query2(ch[las1][tp],ch[las2][tp],ch[p1][tp],ch[p2][tp],k-1,x);
}
}T1,T2; int main()
{
scanf("%d%d",&n,&m); int opt,x,y,z,u,v;
for(int i=1;i<=n;++i) scanf("%d",&val[i]);
for(int i=1;i<n;++i) {
scanf("%d%d",&u,&v);
add(u,v); add(v,u);
}
T1.dfs1(1,0),T2.dfs2(1,0),T2.init();
for(int i=1;i<=m;++i) {
scanf("%d",&opt);
if(opt==1) {
scanf("%d%d",&x,&y);
printf("%d\n",T1.query1(T1.rt[id[x]-1],T1.rt[id[x]+sz[x]-1],30,y));
}
else {
scanf("%d%d%d",&x,&y,&z); int lca=T2.LCA(x,y);
printf("%d\n",T2.query2(T2.rt[f[lca][0]],T2.rt[lca],T2.rt[x],T2.rt[y],30,z));
}
}
return 0;
}

[TJOI2018]异或的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. 洛谷P4592 [TJOI2018]异或(可持久化01Trie)

    题意 题目链接 可持久化01Trie板子题 对于两个操作分别开就行了 #include<bits/stdc++.h> using namespace std; const int MAXN ...

  9. P4592 [TJOI2018]异或

    吐槽 睡起来写道模板清醒一下 貌似有两个log的树剖写法,还有一个log的Trie树的差分做法(类似于count on a tree),然后一个log的要把两个询问分开写,一个dfs序一个差分,然后我 ...

随机推荐

  1. 如何在windows上调试安卓机谷歌浏览器上的页面

    - 下面的方法仅在windows和安卓机上测试过,,,, - 手机(安卓机)需要安装chrome与电脑(Windows)上的chrome配合,也就是只能调试谷歌浏览器上的页面 1.手机的准备工作 打开 ...

  2. yum install oracle-validated

    背景 当时心血来潮要在linux搞oracle,可一顿折腾,大约两个周时间,主要是各种环境的检测麻烦,在redhat上操作也不如centos有利. 命令 yum install oracle-vali ...

  3. python httplib和urllib的性能比较

    httplib代码: urlParseResult = urlparse(url) host = urlParseResult.hostname path = urlParseResult.path ...

  4. Android通讯:通话

    Android通讯之通话功能的实现: 在Android中,android.telephony.TelephonyManager对象是开发者获取当前通话网络相关信息的窗口,通过TelephonyMana ...

  5. Keepalived详解之 - LVS(IPVS)管理工具ipvsadm使用指南

    ipvsadm是什么? ipvsadm是用来配置.维护或者查看Linux内核当中virtual server table的一个工具, LVS(Linux virtual server)能基于一个集群当 ...

  6. LeetCode(55): 跳跃游戏

    Medium! 题目描述: 给定一个非负整数数组,你最初位于数组的第一个位置. 数组中的每个元素代表你在该位置可以跳跃的最大长度. 判断你是否能够到达最后一个位置. 示例 1: 输入: [2,3,1, ...

  7. C++ code:char pointers and char arrays(字符指针与字符数组)

    C-串的正确赋值.复制.修改.比较.连接等方式. #include<iostream> #pragma warning(disable: 4996)//这一句是为了解决“strrev”出现 ...

  8. 【linux】crontab失效

    在linux上,crontab任务全部使用完整路径,但是任务无效. 检测crontab 服务是否启动, /etc/init.d/cron status /etc/init.d/cron restart

  9. hdu3397区间覆盖,区间翻转,区间合并,区间求和

    调了很久的代码..注意区间翻转和覆盖的操作互相的影响 /* 区间替换操作怎么搞? 应该是加个tag标记 如果整个区间都是0|1,那么把若有tag的话直接set1|0即可,也不用设置tag标记 反之要设 ...

  10. ural1855 线段树区间更新+推公式维护一元二次式

    和威威猫系列故事差不多,都是根据条件推出公式 /* 操作c a b d:a到b道路上的所有边权值加d 操作e a b:问a到b中包含的道路的平均权值 区间平均值=所有可能路径权值/所有路径数, 而路径 ...