BZOJ 3261 最大异或和 可持久化Trie

败了败了。。题意很清楚了。

只在队尾添加所以上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[n] xor x(i in [l, r])就转化为sum[n] ^ x ^ sum[i - 1]

而sum[i - 1]与(sum[n] ^ 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], 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[N], **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[n] ^= a[n - 1];
            trie[n] = Trie::put(trie[n - 1], a[n], 1 << 24);
        } else {
            scanf("%d%d%d", &l, &r, &x);
            printf("%d\n", Trie::get(trie[r - 1], trie[l - 2], a[n] ^ 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[N] 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。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值