[bzoj3261]最大异或和[可持久化trie树]

因为要求异或和最大,所以可以考虑从高位开始,向低位枚举尽可能接近~x的值,所以以二进制位为关键字,建立可持久化trie树,根据异或和的性质,XOR_SUM{i,j}=XOR_SUM{1,j} xor XOR_SUM{1,i-1},所以查询问题也可以解决了。

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstdlib>
 5 #include <cstring>
 6 #include <cmath>
 7 #include <ctime>
 8
 9 using namespace std;
10
11 struct    TRIE
12 {
13     int    son[2],val;
14 }trie[25000000];
15
16 int    n,m,tot,Sum[610000];
17 int    root[610000],a[610000];
18
19 void    Insert(const int root_l,int& root_r,const int d,const int step)
20 {
21     trie[root_r=++tot]=trie[root_l];
22     trie[root_r].val++;
23     if(step<0)return ;
24     int    p=(d>>step)&1;
25     Insert(trie[root_l].son[p],trie[root_r].son[p],d,step-1);
26     return ;
27 }
28
29 int    Query(const int d,const int root_l,const int root_r,const int step)
30 {
31     if(step<0)return 0;
32     int    p=(d>>step)&1;
33     if(trie[trie[root_r].son[p^1]].val-trie[trie[root_l].son[p^1]].val)
34         return (1<<step)+Query(d,trie[root_l].son[p^1],trie[root_r].son[p^1],step-1);
35     return Query(d,trie[root_l].son[p],trie[root_r].son[p],step-1);
36 }
37
38 int main()
39 {
40     int    i,x,l,r;
41     char    op[10];
42
43     scanf("%d%d",&n,&m);
44     n++;
45     for(i=2;i<=n;++i)scanf("%d",&a[i]);
46     for(i=1;i<=n;++i)Sum[i]=Sum[i-1]^a[i];
47     for(i=1;i<=n;++i)Insert(root[i-1],root[i],Sum[i],23);
48
49     for(i=1;i<=m;++i)
50     {
51         scanf("%s",op);
52         if(op[0]==‘A‘)
53         {
54             n++;
55             scanf("%d",&a[n]);
56             Sum[n]=Sum[n-1]^a[n];
57             Insert(root[n-1],root[n],Sum[n],23);
58         }
59         else
60         {
61             scanf("%d%d%d",&l,&r,&x);
62             printf("%d\n",Query(Sum[n]^x,root[l-1],root[r],23));
63         }
64     }
65
66     return 0;
67 }
时间: 2024-12-24 01:13:16

[bzoj3261]最大异或和[可持久化trie树]的相关文章

【bzoj3281】最大异或和 可持久化Trie树

题目描述 给定一个非负整数序列 {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 最大,输出最大是多少. 输入 第一行包含两个整数 N  ,M,含义如问题描述所示.   第二行包含 N个非负整数,表示初始的序列 A . 接下来 M行,每行描述一个

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

[BZOJ4103][Thu Summer Camp 2015]异或运算 Description 给定长度为n的数列X={x1,x2,...,xn}和长度为m的数列Y={y1,y2,...,ym},令矩阵A中第i行第j列的值Aij=xi xor  yj,每次询问给定矩形区域i∈[u,d],j∈[l,r],找出第k大的Aij. Input 第一行包含两个正整数n,m,分别表示两个数列的长度 第二行包含n个非负整数xi 第三行包含m个非负整数yj 第四行包含一个正整数p,表示询问次数 随后p行,每行

bzoj4103异或运算 可持久化trie树

要去清华冬令营了,没找到2016年的题,就先坐一坐15年的. 因为n很小,就按照b串建可持久化trie树,a串暴力枚举. 其他的直接看代码. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; inline int read() { int x=0,f=1,ch=getchar(); while(ch<'0'||ch

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

题目大意:给定一个序列,提供下列操作: 1.在数组结尾插入一个数 2.给定l,r,x,求一个l<=p<=r,使x^a[p]^a[p+1]^...^a[n]最大 首先我们可以维护前缀和 然后就是使x^sum[n]^sum[p-1]最大 x^sum[n]为定值,于是用Trie树贪心即可 考虑到l-1<=p-1<=r-1,我们不能对于每个询问都建一棵Trie树,但是我们可以对于Trie数维护前缀和,建立可持久化Trie树 每个区间[l,r]的Trie树为tree[r]-tree[l-1]

bzoj3261: 最大异或和 可持久化trie

题意:给定一个非负整数序列{a},初始长度为N. 有M个操作,有以下两种操作类型: 1.Ax:添加操作,表示在序列末尾添加一个数x,序列的长度N+1. 2.Qlrx:询问操作,你需要找到一个位置p,满足l<=p<=r,使得: a[p] xor a[p+1] xor ... xor a[N] xor x 最大,输出最大是多少. 题解:可持久化trie 用前缀异或来建树,查询就变成了last^x和l到r中a[p]异或最大值是多少 先插入一个0,然后像可持久化线段树那样建树即可,还是挺简单的 /**

bzoj4103[Thu Summer Camp 2015]异或运算(可持久化trie树)

一看数据范围,n很小m很大,对长的那一维建可持久化线段树,另一维暴力枚举 1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int n,m,cnt,tot,p; 7 int rt[300005]; 8 int x[2005]; 9 int y[300005]; 10 struct Trie{ 11 in

[BZOJ3261&amp;BZOJ3166]可持久化trie树及其应用

可持久化trie树 可持久化trie树现在想来是比较好理解的了,但却看了一个下午... 相当于对于每个状态建立一条链(或者说一棵trie),求解的时候只要让两个点按照相同的步子走然后看sum的大小关系即可. tr[y].son[p xor 1]:=tr[x].son[p xor 1]; tr[y].sum:=tr[x].sum+1; 这两句要好好体会,对之后理解query过程中的语句很有帮助. if (tr[tr[x].son[p xor 1]].sum=tr[tr[x].son[p xor 1

【BZOJ3689】异或之 堆+可持久化Trie树

[BZOJ3689]异或之 Description 给定n个非负整数A[1], A[2], ……, A[n].对于每对(i, j)满足1 <= i < j <= n,得到一个新的数A[i] xor A[j],这样共有n*(n-1)/2个新的数.求这些数(不包含A[i])中前k小的数.注:xor对应于pascal中的“xor”,C++中的“^”. Input 第一行2个正整数 n,k,如题所述.以下n行,每行一个非负整数表示A[i]. Output 共一行k个数,表示前k小的数. Samp

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

3261: 最大异或和 Time Limit: 10 Sec  Memory Limit: 512 MB 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 最大,输出最大是多少. Inp