题目分析:

  很无聊的一道题目。首先区间内单点对应异或值的询问容易想到trie树。由于题目在树上进行,case1将路径分成两段,然后dfs的时候顺便可持久化trie树做询问。case2维护dfs序,对dfs序建可持久化的trie树。这样做的空间复杂度是O(nw),时间复杂度是O(nw).

代码:

 #include<bits/stdc++.h>
using namespace std; const int maxn=; int n,q;
int v[maxn];
vector<int> g[maxn]; vector<pair<int,int> > qy[maxn];
vector<pair<int,int> > vec; int ans[maxn],num,kd[maxn];
int dep[maxn],dfsin[maxn],dfsout[maxn],fa[maxn]; vector<pair<int,int> > Lca[maxn];
int pre[maxn]; int found(int x){
int rx = x; while(pre[rx] != rx) rx = pre[rx];
while(pre[x] != rx){
int t = pre[x]; pre[x] = rx; x = t;
}
return rx;
} void dfs(int now,int dp,int f){
dfsin[now] = dfsout[now] = ++num;fa[now] = f; dep[now] = dp;
for(auto pr:Lca[now]){
if(dep[pr.first] == ) continue;
int la = found(pr.first);
qy[now].push_back(make_pair(la,pr.second));
qy[pr.first].push_back(make_pair(la,pr.second));
}
for(auto i:g[now]){
if(i == f) continue;
dfs(i,dp+,now);
dfsout[now] = dfsout[i];
}
pre[found(now)] = found(f);
} void read(){
scanf("%d%d",&n,&q);
for(int i=;i<=n;i++) scanf("%d",&v[i]);
for(int i=;i<n;i++){
int x,y; scanf("%d%d",&x,&y);
g[x].push_back(y); g[y].push_back(x);
}
for(int i=;i<=q;i++){
int cas; scanf("%d",&cas);
if(cas == ){
int x,y; scanf("%d%d",&x,&y);
vec.push_back(make_pair(x,i));kd[i] = y;
}else{
int x,y,z; scanf("%d%d%d",&x,&y,&z);
Lca[x].push_back(make_pair(y,i));
if(x!=y) Lca[y].push_back(make_pair(x,i));
kd[i] = z;
}
}
for(int i=;i<=n;i++) pre[i] = i;
dfs(,,);
} int his[maxn],om;
int sz[maxn*],ch[maxn*][]; void follow(int pt,int last,int dt){
int hbit = ;
while(hbit!=-){
if((<<hbit)&dt){
ch[pt][] = ch[last][];
ch[pt][] = ++num;
pt = num; last = ch[last][];
sz[pt] = sz[last]+;
}else{
ch[pt][] = ch[last][];
ch[pt][] = ++num;
pt = num; last = ch[last][];
sz[pt] = sz[last]+;
}
hbit--;
}
} void ins(int now){
int last = his[om-];
num++;int pt = num; sz[pt] = sz[last]+;
his[om] = num;
follow(pt,last,v[now]);
} int query(int now,int last,int z){
now = his[now]; last = his[last];
int hbit = ;
while(hbit!=-){
if((<<hbit)&z){
if(sz[ch[now][]]-sz[ch[last][]]){
now = ch[now][];last = ch[last][];
}else{
z -= (<<hbit);now = ch[now][];last = ch[last][];
}
}else{
if(sz[ch[now][]]-sz[ch[last][]]){
z += (<<hbit);
now = ch[now][];last = ch[last][];
}else{
now = ch[now][];last = ch[last][];
}
}
hbit--;
}
return z;
} void del(int now){his[om] = ;} void dfs2(int now){
om++;ins(now);
for(auto pr:qy[now]){
int last = dep[pr.first]-,data = kd[pr.second];
ans[pr.second] = max(ans[pr.second],query(dep[now],last,data));
}
for(auto i:g[now]){
if(i == fa[now]) continue;
dfs2(i);
}
del(now);om--;
} void dfs3(int now){
om++;ins(now);
for(auto i:g[now]){
if(i == fa[now]) continue;
dfs3(i);
}
} void work(){
num = ;his[] = ;
dfs2();
memset(ch,,sizeof(ch));memset(sz,,sizeof(sz));
num = ;his[] = ;om = ;
dfs3();
for(auto pr:vec){
int st = dfsin[pr.first],ed = dfsout[pr.first];
ans[pr.second] = query(ed,st-,kd[pr.second]);
}
for(int i=;i<=q;i++) printf("%d\n",ans[i]);
} int main(){
read();
work();
return ;
}

BZOJ5338 [TJOI2018] Xor 【可持久化Trie树】【dfs序】的更多相关文章

  1. [BZOJ5338][TJOI2018]xor(可持久化Trie)

    可持久化Trie模板题. 建两种可持久化Trie,每个点两棵,一棵对DFS求前缀和,一棵对祖先求前缀和. 或者树剖,不好写多少还多个log. #include<cstdio> #inclu ...

  2. Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序

    题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s   内存限制:512.0MB    总提交次数:196   AC次数:65   平均分: ...

  3. BZOJ.5338.[TJOI2018]xor(可持久化Trie)

    BZOJ LOJ 洛谷 惊了,18年了还有省选出模板题吗= = 做这题就是练模板的,我就知道我忘的差不多了 询问一就用以DFS序为前缀得到的可持久化Trie做,询问二很经典的树上差分. 注意求询问二的 ...

  4. 【CF768G】The Winds of Winter 可持久化线段树 DFS序

    题目大意 给定一棵\(n\)个点的树,对于树上每个结点,将它删去,然后可以将得到的森林中任意一个点与其父亲断开并连接到另一颗树上,对每一个点求出森林中所有树\(size\)最大值的最小值. \(n\l ...

  5. 2018.10.20 NOIP模拟 巧克力(trie树+dfs序+树状数组)

    传送门 好题啊. 考虑前面的32分,直接维护后缀trietrietrie树就行了. 如果#号不在字符串首? 只需要维护第一个#前面的字符串和最后一个#后面的字符串. 分开用两棵trie树并且维护第一棵 ...

  6. BZOJ3653谈笑风生——可持久化线段树+dfs序

    题目描述 设T 为一棵有根树,我们做如下的定义: ? 设a和b为T 中的两个不同节点.如果a是b的祖先,那么称“a比b不知道 高明到哪里去了”. ? 设a 和 b 为 T 中的两个不同节点.如果 a ...

  7. BZOJ 5338: [TJOI2018]xor 可持久化trie+dfs序

    强行把序列问题放树上,好无聊啊~ code: #include <bits/stdc++.h> #define N 200005 #define setIO(s) freopen(s&qu ...

  8. [TJOI2018] Xor 异或 (可持久化Trie,树链剖分)

    题目描述 现在有一颗以 1 为根节点的由 n 个节点组成的树,树上每个节点上都有一个权值 \(v_i\).现在有 Q 次操作,操作如下: 1 x y :查询节点 x 的子树中与 y 异或结果的最大值. ...

  9. 可持久化trie(BZOJ5338: [TJOI2018]xor)

    题面 BZOJ Sol 显然是要维护一个区域的 \(trie\) 树,然后贪心 区间 \(trie\) 树??? 可持久化 \(trie\) 树??? 直接参考主席树表示出区间的方法建立 \(trie ...

随机推荐

  1. Java多线程编程模式实战指南一:Active Object模式(上)

    Active Object模式简介 Active Object模式是一种异步编程模式.它通过对方法的调用与方法的执行进行解耦来提高并发性.若以任务的概念来说,Active Object模式的核心则是它 ...

  2. React-性能优化pureComponent

    每当store里有数据更新时,render()函数就会执行,有时候store的更新数据与本组件并没有关系,render()不必执行. 我们可以用shouldComponentUpdate来优化组件. ...

  3. 2011 noip 提高组

    首先吐槽:刚刚写着写着突然蓝屏了,,emmm,写到最后一题了蓝屏了. 当时我的内心是崩溃的. 然后,旁边的大佬默默来了一句:论保存草稿的重要性. 连着蓝了三次之后开了防火墙,然后,,我左边那位同学又开 ...

  4. linux journalctl 命令

    目录 Help 输出所有的日志记录 匹配(match) 把日志保存到文件中 限定日志所能占用的最高容量 查看某次启动后的日志 查看指定时间段的日志 同时应用 match 和时间过滤条件 按 unit ...

  5. Gerrit上分支操作记录(创建分支、删除分支)

    Git分支对于一个项目的代码管理而言,是十分重要的!许多久用git的朋友可能已经掌握的很牢固了,但对于一些初涉git的童鞋来说,可能还不是很熟悉.在此,我将自己的一些操作经历做一梳理,希望能帮助到有用 ...

  6. Python_初识函数和返回值_22

    #len s = '金老板小护士' len(s) def my_len(): #自定义函数 i = 0 for k in s: i += 1 print(i) length = my_len() pr ...

  7. 代码规范与复审2——个人博客作业week

    一.关于编程规范的重要性论证 1.不支持. 1)编程规范有利于自己提高编程效率和编程质量.编码是程序员的职责,一个好的信息技术产品必然有高质量的代码,高质量的代码首先 一点它必须遵守某种编程规范.如果 ...

  8. mooc linux学习总结

    通过八周的学习获得了很多知识.       首先,通过网课老师形象生动的讲述和描述一些专业词汇,使我更加深刻的记住并掌握了这些内容:动态的展示堆栈的变化,更容易理解一段汇编代码:分析操作系统的工作,记 ...

  9. Linux内核分析——字符集总结与分析

      一.  设置修改系统.应用默认字符集 1. 查看虚拟机的字符集: 由此可见,该虚拟机的字符集为zh_CN.UTF-8. 2. 查看服务器支持的编码方式 3. 修改字符集类型 上图可见,LANG字符 ...

  10. 在WIN10打造成能运行Oracle的JDK的Linux

    1.开发WindowsFeature(程序)里的Linux扩展接口(其实从Windows2008发布前试用时,就发现悄悄藏着一个Unix接口选项). 2.在windows应用商店可以下载到Ubuntu ...