BZOJ3261 最大异或和

这是是一道可持久化数据结构题。具体分类不明

按二进制位建立一颗可持久化树:

因为每个节点都有两个儿子,于是非常像线段树,但是其实本质又是trie,于是就叫它可持久化trie吧。。。

每次新家点的时候就在trie里加一条链,然后查询用贪心方法查即可。

 1 /**************************************************************
 2     Problem: 3261
 3     User: rausen
 4     Language: C++
 5     Result: Accepted
 6     Time:4168 ms
 7     Memory:191432 kb
 8 ****************************************************************/
 9  
10 #include <cstdio>
11 #include <cstring>
12 #include <algorithm>
13  
14 using namespace std;
15  
16 struct trie_node{
17     int sum, son[2];
18 } tr[16000000];
19  
20 int n, m, last, tot, root[800000];
21  
22 void ins(int x, int &y, int V, int D){
23     y = ++tot, tr[y].sum = tr[x].sum + 1;
24     if (D < 0) return;
25     int p = (V >> D) & 1;
26     tr[y].son[p ^ 1] = tr[x].son[p ^ 1];
27     ins(tr[x].son[p], tr[y].son[p], V, D - 1);
28 }
29  
30 int query(int x, int y, int V, int D){
31     if (D < 0) return 0;
32     int p = (V >> D) & 1;
33     if (tr[tr[x].son[p ^ 1]].sum == tr[tr[y].son[p ^ 1]].sum)
34         return query(tr[x].son[p], tr[y].son[p], V, D - 1);
35     else return query(tr[x].son[p ^ 1], tr[y].son[p ^ 1], V, D - 1) + (1 << D);
36 }
37  
38 int main(){ 
39     scanf("%d%d", &n, &m);
40     int L, R, X;
41     ++n, tot = 0;
42     tr[0].son[0] = tr[0].son[1] = tr[0].sum = 0;
43     ins(root[0], root[1], 0, 24);
44     last = 0;
45     for (int i = 2; i <= n; ++i){
46         scanf("%d", &X);
47         ins(root[i - 1], root[i], last ^= X, 24);
48     }
49  
50     char CH;
51     while (m--){
52         scanf("
%c", &CH);
53         if (CH == 'A'){
54             scanf("%d", &X), ++n;
55             ins(root[n - 1], root[n], last ^= X, 24);
56         } else{
57             scanf("%d%d%d", &L, &R, &X);
58             printf("%d
", query(root[L - 1], root[R], last ^ X, 24));
59         }
60     }
61     return 0;
62 }
View Code

 p.s. AC100纪念(虽然好多好多水题。。>.<)

By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
原文地址:https://www.cnblogs.com/rausen/p/4005310.html