BZOJ 3261 最大异或和 可持久化Trie
2015-12-29 21:25
543 查看
败了败了。。题意很清楚了。
只在队尾添加所以上Trie。
a[l,r] xor结果在我程序中应该写的是trie[l-2], trie[r-1],然而我写了trie[l-1], trie[r]。。。WAWAWA。。。
令sum[i] = a[1] xor a[2] xor ... xor a[i],
有a[l] xor a[l+1] xor ... xor a[r] = sum[r] xor sum[l - 1]
所以题意要求a[i] xor ... xor a
xor x(i in [l, r])就转化为sum
^ x ^ sum[i - 1]
而sum[i - 1]与(sum
^ x)的xor的最大值可以查询可持久化trie。
因为i∈[l, r],所以i - 1 ∈[l - 1, r - 1],所以查询trie[l - 2]和trie[r - 1]。。。。
写的有点乱,不过还是可以看的~
怎么感觉这个程序对可持久化Trie的包装很怪异,写的很不优雅。。所以参考了popoqqq神的模板。。函数式写法深入我心。
Submit: 965 Solved: 405
[Submit][Status][Discuss]
给定一个非负整数序列 {a},初始长度为 N。
有 M个操作,有以下两种操作类型:
1 、A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1。
2 、Q l r x:询问操作,你需要找到一个位置 p,满足 l<=p<=r,使得:
a[p] xor a[p+1] xor ... xor a
xor x 最大,输出最大是多少。
第二行包含 N个非负整数,表示初始的序列 A 。
接下来 M行,每行描述一个操作,格式如题面所述。
2 6 4 3 6
A 1
Q 3 5 4
A 4
Q 5 7 0
Q 3 6 6
5
6
对于测试点 3-7,N,M<=80000 。
对于测试点 8-10,N,M<=300000 。
其中测试点 1, 3, 5, 7, 9保证没有修改操作。
对于 100% 的数据, 0<=a[i]<=10^7。
只在队尾添加所以上Trie。
a[l,r] xor结果在我程序中应该写的是trie[l-2], trie[r-1],然而我写了trie[l-1], trie[r]。。。WAWAWA。。。
令sum[i] = a[1] xor a[2] xor ... xor a[i],
有a[l] xor a[l+1] xor ... xor a[r] = sum[r] xor sum[l - 1]
所以题意要求a[i] xor ... xor a
xor x(i in [l, r])就转化为sum
^ x ^ sum[i - 1]
而sum[i - 1]与(sum
^ x)的xor的最大值可以查询可持久化trie。
因为i∈[l, r],所以i - 1 ∈[l - 1, r - 1],所以查询trie[l - 2]和trie[r - 1]。。。。
写的有点乱,不过还是可以看的~
怎么感觉这个程序对可持久化Trie的包装很怪异,写的很不优雅。。所以参考了popoqqq神的模板。。函数式写法深入我心。
#include <cstdio> const int N = 600001; int a , n, m; struct Trie { Trie* c[2]; int size; Trie() { c[0] = c[1] = this; size = 0; } Trie(Trie *l, Trie *r, int sz) { c[0] = l, c[1] = r, size = sz; } void* operator new(size_t) { static Trie pool[N * 30], *pointer = pool; return pointer++; } static Trie* put(Trie *p, int x, int digit) { if (!digit) return new Trie(p->c[0], p->c[1], p->size + 1); if (x & digit) return new Trie(p->c[0], put(p->c[1], x, digit >> 1), p->size + 1); else return new Trie(put(p->c[0], x, digit >> 1), p->c[1], p->size + 1); } static int get(const Trie *p1, const Trie *p2, int x, int digit) { if (!digit) return 0; bool t = bool(~x & digit); if (p1->c[t]->size - p2->c[t]->size) return digit | get(p1->c[t], p2->c[t], x, digit >> 1); else return get(p1->c[t ^ 1], p2->c[t ^ 1], x, digit >> 1); } } *trie_impl , **trie = trie_impl + 1; int main() { int i, l, r, x; char p[10]; scanf("%d%d", &n, &m); for (i = 1; i <= n; i++) scanf("%d", a + i), a[i] ^= a[i - 1]; trie[-1] = new Trie(); for (i = 0; i <= n; i++) trie[i] = Trie::put(trie[i - 1], a[i], 1 << 24); while (m--) { scanf("%s", p); if (p[0] == 'A') { scanf("%d", &a[++n]); a ^= a[n - 1]; trie = Trie::put(trie[n - 1], a , 1 << 24); } else { scanf("%d%d%d", &l, &r, &x); printf("%d\n", Trie::get(trie[r - 1], trie[l - 2], a ^ x, 1 << 24)); } } return 0; }
3261: 最大异或和
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 965 Solved: 405
[Submit][Status][Discuss]
Description
给定一个非负整数序列 {a},初始长度为 N。
有 M个操作,有以下两种操作类型:
1 、A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1。
2 、Q l r x:询问操作,你需要找到一个位置 p,满足 l<=p<=r,使得:
a[p] xor a[p+1] xor ... xor a
xor x 最大,输出最大是多少。
Input
第一行包含两个整数 N ,M,含义如问题描述所示。第二行包含 N个非负整数,表示初始的序列 A 。
接下来 M行,每行描述一个操作,格式如题面所述。
Output
假设询问操作有 T个,则输出应该有 T行,每行一个整数表示询问的答案。Sample Input
5 52 6 4 3 6
A 1
Q 3 5 4
A 4
Q 5 7 0
Q 3 6 6
Sample Output
45
6
HINT
对于测试点 1-2,N,M<=5 。对于测试点 3-7,N,M<=80000 。
对于测试点 8-10,N,M<=300000 。
其中测试点 1, 3, 5, 7, 9保证没有修改操作。
对于 100% 的数据, 0<=a[i]<=10^7。
相关文章推荐
- 跑批利器--读取文件
- myeclipse 8.6 安装svn插件
- 1229作业
- integer.valueof()和integer.parseint区别
- vijos 1234 口袋的天空
- Linux安装JDK、MyEclipse、MySql
- HDU计算机学院大学生程序设计竞赛(2015’12)The Magic Tower
- 【IOS 开发】基本 UI 控件详解 (UIDatePicker | UIPickerView | UIStepper | UIWebView | UIToolBar )
- bzoj1084[SCOI2005]最大子矩阵
- 跑批利器--示例
- 第十六周--数据结构--项目一--插入排序之折半插入排序
- linux screen命令 关闭远程连接程序继续运行
- 程序员逆袭应具备的7大技能
- string to int
- 蓝懿ios练习整理笔记
- Android Studio——PendingIntent的Flags
- 利用一致性哈希水平拆分MySql单表
- 这些哭笑不得的情景,每一个程序猿都可能面对
- Perl中的替换(七)
- 【VS调试】C#读写Windows 7注册表时抛出“不允许所请求的注册表访问权”的解决办法