这题我借鉴了“主席树”的思想。
令v_i = x_1 ^ x_2 ^ ... ^ x_i 将v写成二进制,建立可持久化trie。
对于增加一个数,就相当于多开一个版本。
对于一个询问l,r,x,相当于求v_i ^ (v_N ^ x)最大(l - 1 <= i <= r - 1)。v_N ^ x是定值,于是贪心地找i就可以了。也就是对于一个v_N ^ x的二进制位是0则尽量在可持久化trie中找这位是1的。反之亦然。
实现的时候有个细节,就是可以在数列的最前面加一个0,这样方便处理。
时间复杂度O((N+M)*log 10^7) = O((N+M)*24) 空间复杂度大约为O((N+M)*24)
(如果在IE浏览器下要拷代码的话复制到word里面就行了,虽然我也不知道为什么)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
/**************************************************************
Problem: 3261
User: lazycal
Language: C++
Result: Accepted
Time:4436 ms
Memory:174244 kb
****************************************************************/
#include <cstdio>
const
int
N = 600000 + 9;
int
root[N],v[N],Vc,num,t[25];
struct
Tree
{
int
lc,rc,size;
}tree[N*24];
inline
void
ten_to_two(
int
x,
int
(&t)[25])
{
t[0] = 0;
for
(;x;x/=2) t[++t[0]] = x&1;
for
(
int
i = t[0] + 1;i <= 24; ++i) t[i] = 0;
}
inline
void
Add(
int
x)
{
++num;
v[num] = x^v[num - 1];
ten_to_two(v[num],t);
root[num] = Vc + 1;
int
las = root[num - 1];
for
(
int
i = 24; i; --i) {
tree[++Vc] = tree[las]; ++tree[Vc].size;
if
(t[i]) las = tree[las].rc, tree[Vc].rc = Vc + 1;
else
las = tree[las].lc, tree[Vc].lc = Vc + 1;
}
tree[++Vc] = tree[las]; ++tree[Vc].size;
}
inline
int
zero_num(
const
int
lt,
const
int
rt)
{
return
tree[tree[rt].lc].size - tree[tree[lt].lc].size;}
inline
int
one_num(
const
int
lt,
const
int
rt)
{
return
tree[tree[rt].rc].size - tree[tree[lt].rc].size;}
int
Query(
int
lt,
int
rt,
int
x)
{
ten_to_two(x,t);
int
ans = 0;
for
(
int
i = 24; i; --i) {
if
(t[i]) {
if
(zero_num(lt,rt)) lt = tree[lt].lc,rt = tree[rt].lc;
else
lt = tree[lt].rc,rt = tree[rt].rc,t[i] = 0;
}
else
{
if
(one_num(lt,rt)) lt = tree[lt].rc,rt = tree[rt].rc,t[i] = 1;
else
lt = tree[lt].lc,rt = tree[rt].lc;
}
if
(t[i]) ans |= 1 << i-1;
}
return
ans;
}
int
main()
{
int
n,m;
scanf
(
"%d%d"
,&n,&m);
root[0] = ++Vc;
Add(0);
for
(
int
i = 1,x; i <= n; ++i)
{
scanf
(
"%d"
,&x);Add(x);}
char
c;
for
(
int
x,l,r;m--;) {
scanf
(
"\n%c"
,&c);
if
(c ==
'A'
) {
scanf
(
"%d"
,&x);Add(x);}
else
{
scanf
(
"%d%d%d"
,&l,&r,&x);
printf
(
"%d\n"
,Query(root[l - 1],root[r],x^v[num]));
}
}
}
|