'''
假设原序列是a(1), a(2), .... a(N)
其异或前缀和序列是S(0), S(1), S(2).... S(N)
则题目求的是在区间L, R 中找一个P,让S(P-1) ^ S(N) ^ x 最大
其实就是普通的最大异或和问题,可用前缀树结合贪心算法解决,
只不过需要注意怎么满足P在L,R之间这个约束,用可持久化前缀树维护
每一个版本的前缀树,可以保证从第R个版本的根开始搜索,所有搜到的
S(P)中P是小于等于R的,还需要在Trie节点中维护每一个节点为根的
子树中所有单词的最大编号,每次搜索时候需要验证当前走的路径中下一个
节点的子树中的最大单词编号是否是大于等于L的,这样就用可持久化的
前缀树搜索满足了P在L和R之间的约束
'''
import sys
class TrieNode:
def __init__(self):
self.next = [None, None]
self.is_end = False
self.max_word_idx = -1 # 节点为根的子树包含的单词的最大序号(序号从0开始)
class PersistentTrie:
def __init__(self):
self.root_entry = [] # 每一个版本的根节点,版本号从0开始
def append(self, s: str):
self.root_entry.append(TrieNode())
prev_cur = self.root_entry[-2] if len(self.root_entry) >= 2 else None # 上一个版本的当前节点
cur = self.root_entry[-1] # 当前版本的当前节点
cur_idx = len(self.root_entry)-1
cur.max_word_idx = max(cur.max_word_idx, cur_idx)
for ch in s:
if prev_cur is not None:
cur.next = prev_cur.next[::] # 拷贝上一个版本的指针
ch = ord(ch) - ord('0')
new_node = TrieNode()
cur.next[ch] = new_node
cur = cur.next[ch]
if prev_cur is not None:
prev_cur = prev_cur.next[ch]
cur.max_word_idx = max(cur.max_word_idx, cur_idx)
cur.is_end = True
def getRoot(self, version) -> TrieNode:
return self.root_entry[version]
n, m = map(int, input().split())
s = sys.stdin.readline()
arr = list(map(int, s.split()))
S = arr[::] # 前缀和
for i in range(1, n):
S[i] ^= S[i-1]
def val2binstr(val):
base = 1 << 24
s = ''
while base > 0:
if val & base:
s += '1'
else:
s += '0'
base >>= 1
return s
trie = PersistentTrie()
trie.append(val2binstr(0))
for i, val in enumerate(S):
trie.append(val2binstr(val))
for i in range(m):
s = sys.stdin.readline()
if s[0] == 'A':
_, val = s.split()
val = int(val)
S.append(S[-1] ^ val)
trie.append(val2binstr(S[-1]))
else:
_, start, end, x = s.split()
start, end, x = int(start), int(end), int(x)
start, end = start-1, end-1
# 在start到end中找p 让S[p] ^ (S[-1] ^ x) 最大
# cur 当前遍历的树节点
# cur_bit 当前在处理哪一位
# val (S[-1] ^ x)的数值
# 返回选出的最佳的S[p]
def dfs(cur: TrieNode, cur_bit: int, val:int):
if cur_bit == -1:
return 0
cur_bit_val = val & (1 << cur_bit)
if cur_bit_val == 0:
if cur.next[1] is not None and cur.next[1].max_word_idx >= start:
return (1 << cur_bit) | dfs(cur.next[1], cur_bit-1, val)
else:
return dfs(cur.next[0], cur_bit-1, val)
else:
if cur.next[0] is not None and cur.next[0].max_word_idx >= start:
return dfs(cur.next[0], cur_bit-1, val)
else:
return (1 << cur_bit) | dfs(cur.next[1], cur_bit-1, val)
select_val = dfs(trie.getRoot(end), 24, S[-1]^x)
sys.stdout.write(str(select_val ^ S[-1]^x) + '\n')