您的位置:首页 > 其它

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神的模板。。函数式写法深入我心。

#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 MB
Submit: 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 5

2 6 4 3 6

A 1

Q 3 5 4

A 4

Q 5 7 0

Q 3 6 6

Sample Output

4

5

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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: