可持久化Trie树和可持久化线段树很像,依次插入信息,通过减法来进行历史版本查询。

2015年11月27日

  bzoj3261 最大异或和

    我们需要计算 a[p] xor a[p+1] xor ... xor a[N] xor x ,设 sum[i] 表示 a[1] xor a[2] xor ... xor a[i] 的值,因为异或满足区间减法,所以求上一个式子等于求 sum[n] xor sum[p - 1] xor x,进一步,sum[n] xor x 为定值,所以需要找到二进制位上尽量不匹配的,由此需要使用Trie树。

    同时题目中有区间限制,所以我们需要一个可持久化的数据结构。

    1) 顺次将sum[i]插入到可持久化Trie树中。注意 : 我们需要让数位对齐,否则高位低位会错位,所以需要在每一个数的前面加上适当的0以使他们数位相等。

    插入时,可以采取递归的方式,用 >> 来确定这一位是多少,把没有改变的那一边链向历史版本。注意 : 在递归时,若采取d--(此处见代码)的方式,因为一个节点的左右儿子不是在同一个递归中构造完成,所以判断 d < 0  ---> break; 需要放在新建节点之后。

    2) 对于查询时,从根节点开始,同样采用d--的方式,逐位确定,如果 x 的这一位为 p ,那么我们查询Sum[son[l][p ^ 1]] - Sum[son[r][p ^ 1],Sum为节点上有多少的值,如若 表达式 > 0 那么我们就像 p ^ 1 的方向行走,同时 答案加上 1 << d 因为这一位被我们错开了,否则只好向 p 的方向行走, 不加上 1 << d。

    3) 因为我们要计算的是 sum[p - 1] xor sum[n] xor[x] 的值,所以对于给定的p的限制区间,我们必须把区间减一,再把左端点减一后查询,这里有一个小技巧 : 首先插入一个 0 的值到可持久化Trie树中,以作为第一个节点,对于后面的读入 比如说(l, r) 直接查询 (l - 1, r) 即可,因为已经事先减一了。

    4) 对于空间的问题,因为一条链最多有 floor(log(1e7)) + 1 的长度,又因为 n <= 300000, m <= 300000,有可能所有的option均为A,所以 (Maxn + Maxm) * (floor(log(1e7)) + 1)

 #include <bits/stdc++.h>
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define REP(i, a, b) for (int i = a; i < b; i++)
#define drep(i, a, b) for (int i = a; i >= b; i--)
#define pb push_back
#define mp make_pair
#define xx first
#define yy second
using namespace std;
typedef long long i64;
typedef pair<int, int> pii;
const int inf = ~0U >> ;
const i64 INF = ~0ULL >> ;
//*****************************
const int maxn = , maxm = ; int Sum[maxm], Son[maxm][], root[maxm], ndtot; void build(int x, int &y, int v, int d) {
Sum[y = ++ndtot] = Sum[x] + ;
if (d < ) return;
int p = v >> d & ;
Son[y][p ^ ] = Son[x][p ^ ];
build(Son[x][p], Son[y][p], v, d - );
} int tot; int query(int x, int y, int v, int d) {
if (d < ) return ;
int p = v >> d & ; int tmp = Sum[Son[y][p ^ ]] - Sum[Son[x][p ^ ]];
if (tmp > ) return ( << d) + query(Son[x][p ^ ], Son[y][p ^ ], v, d - );
else return query(Son[x][p], Son[y][p], v, d - );
} int main() {
int n, m;
scanf("%d%d", &n, &m);
build(root[], root[], , ), n++;
rep(i, , n) {
int id;
scanf("%d", &id);
tot ^= id;
build(root[i - ], root[i], tot, );
}
char op[];
while (m--) {
scanf("%s", op);
if (op[] == 'A') {
int id;
scanf("%d", &id);
tot ^= id;
build(root[n], root[n + ], tot, );
n++;
}
else {
int x, y, k;
scanf("%d%d%d", &x, &y, &k);
printf("%d\n", query(root[x - ], root[y], tot ^ k, ));
}
}
}

      

可持久化Trie树初步的更多相关文章

  1. [十二省联考2019]异或粽子——可持久化trie树+堆

    题目链接: [十二省联考2019]异或粽子 求前$k$大异或区间,可以发现$k$比较小,我们考虑找出每个区间. 为了快速得到一个区间的异或和,将原序列做前缀异或和. 对于每个点作为右端点时,我们维护出 ...

  2. BZOJ4477[Jsoi2015]字符串树——可持久化trie树

    题目描述 萌萌买了一颗字符串树的种子,春天种下去以后夏天就能长出一棵很大的字符串树.字符串树很奇特,树枝上都密密麻麻写满了字符串,看上去很复杂的样子.[问题描述]字符串树本质上还是一棵树,即N个节点N ...

  3. BZOJ5338 [TJOI2018] Xor 【可持久化Trie树】【dfs序】

    题目分析: 很无聊的一道题目.首先区间内单点对应异或值的询问容易想到trie树.由于题目在树上进行,case1将路径分成两段,然后dfs的时候顺便可持久化trie树做询问.case2维护dfs序,对d ...

  4. 51nod 1295 XOR key (可持久化Trie树)

    1295 XOR key  题目来源: HackerRank 基准时间限制:1.5 秒 空间限制:262144 KB 分值: 160 难度:6级算法题   给出一个长度为N的正整数数组A,再给出Q个查 ...

  5. 【BZOJ-4212】神牛的养成计划 Trie树 + 可持久化Trie树

    4212: 神牛的养成计划 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 136  Solved: 27[Submit][Status][Discus ...

  6. 51nod 1295 XOR key | 可持久化Trie树

    51nod 1295 XOR key 这也是很久以前就想做的一道板子题了--学了一点可持久化之后我终于会做这道题了! 给出一个长度为N的正整数数组A,再给出Q个查询,每个查询包括3个数,L, R, X ...

  7. 【bzoj2741】[FOTILE模拟赛]L 可持久化Trie树+分块

    题目描述 FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor A ...

  8. bzoj 3261: 最大异或和 (可持久化trie树)

    3261: 最大异或和 Time Limit: 10 Sec  Memory Limit: 512 MB Description       给定一个非负整数序列 {a},初始长度为 N.       ...

  9. BZOJ4103 [Thu Summer Camp 2015]异或运算 【可持久化trie树】

    题目链接 BZOJ4103 题解 一眼看过去是二维结构,实则未然需要树套树之类的数据结构 区域异或和,就一定是可持久化\(trie\)树 观察数据,\(m\)非常大,而\(n\)和\(p\)比较小,甚 ...

随机推荐

  1. 17232 伪Acmer的推理(传递闭包)

    17232 伪Acmer的推理 时间限制:1000MS  内存限制:65535K提交次数:0 通过次数:0 收入:0 题型: 编程题   语言: G++;GCC Description 现在正是期末, ...

  2. Light OJ 1008

    找规律. 首先令n=sqrt(s),上取整.讨论当n为偶数时,若n*n-s<n则x=n,y=n*n-s+1否则x=-n*n+2*n+s-1,y=n;如果n为奇数,交换x,y即可,对称的. Sam ...

  3. java项目(java project)如何导入jar包的解决方案列表

    右键项目-properties-java build path(左侧菜单)-选择libraries 有两种方式,导入jar包实际上就是建立一种链接,并不是copy式的导入 一.导入外部包,add ex ...

  4. MFC的核心概念

    API是英文Application Programming Interface 的缩写,意思是“应用程序接口”,泛指系统为应用程序提供的一系列函数接口,在编程时可以直接调用,而不必知道其内部实现的过程 ...

  5. AutoFac使用方法总结

    AutoFac是.net平台下的IOC容器产品,它可以管理类之间的复杂的依赖关系.在使用方面主要是register和resolve两类操作. 这篇文章用单元测试的形式列举了AutoFac的常用使用方法 ...

  6. c# 如何判断字符串中相同字符串的个数 (相同字符在字符串中出现的次数)

    /// <summary> /// 计算字符串中子串出现的次数 /// </summary> /// <param name="str">字符串 ...

  7. 修改sqlserver的数据库排序规则语句

    alter database SOETMS collate Chinese_PRC_CI_AS

  8. 你的float用对了吗

    介绍 很多人都知道float是浮点类型,它不能表示数据范围内的所有数值.但是,实际使用或编码时,你又是否记得这句话呢?下面是stackoverflow中的一个问题: why does a float ...

  9. 利用cookie实现“只弹出一次窗口”的JS代码

    弹出式窗口通常被用来做弹出广告(CPM),其实用弹出式窗口用来做消息通知也是最普遍而且是最有效的方法,但如果每次刷新页面特别是刷新首页都要弹出窗口的话,那绝对是让访问者厌烦的事情. 比如你将上面的脚本 ...

  10. Java正则表达式细节1

     Java中使用特定的字符类别比如 \d \s \w \d 匹配数字 \s 匹配空白字符 \w 匹配数字或者字符或者下划线[a-zA-Z0-9_] 比如使员正则的时候: 使用的是2个 斜杠 @Test ...