📌  相关文章
📜  对于给定的一组查询,求给定范围 [L, R] 中的元素与值 K 的异或(1)

📅  最后修改于: 2023-12-03 15:25:11             🧑  作者: Mango

题目:对于给定的一组查询,求给定范围 [L, R] 中的元素与值 K 的异或

题目描述

给定一个数组和若干个查询,每个查询包含一个数 x 和两个整数 l,r。对于每个查询,求出 l<=i<=r 且 arr[i] 与 x 的异或值。

输入格式

第一行包含一个整数 n,表示数组长度。

第二行包含 n 个整数,表示数组中的元素。

接下来一行包含一个整数 q,表示查询个数。

接下来 q 行,每行包含一个整数 x 和两个整数 l,r,表示一次查询的具体范围。

输出格式

对于每个询问,输出一个整数,表示对于每个查询,求出 l<=i<=r 且 arr[i] 与 x 的异或值。

样例

输入样例:

6
1 2 3 4 5 6
3
2 2 4
3 1 3
4 4 6

输出样例:

1
2
2
分析

​ 该题需要对每个查询进行处理,对于每个查询 x 和区间 [l, r],需要求出数组 arr[] 中,与给定数 x 异或后,在区间 [l, r] 内元素异或的结果。

​ 在暴力解法的基础上可以采用线段树进行优化,线段树节点记录的信息为当前区间内所有元素的异或结果。每次查询时,递归询问线段树,将查询区间一分为二,分别对左右区间进行递归,直到查询区间与线段树节点区间重叠,此时判断节点所代表的区间与查询区间是否完全重合,若重合,则返回该节点记录的异或结果,否则继续递归。

代码
class SegmentTree:
    def __init__(self, data):
        self.l = 0
        self.r = len(data) - 1
        self.data = data
        self.tree = [0] * 4 * len(data)
        self.build(0, self.l, self.r)
    
    def build(self, node, l, r):
        if (l == r):
            self.tree[node] = self.data[l]
            return 
        mid = (l + r) >> 1
        self.build(node*2+1, l, mid)
        self.build(node*2+2, mid+1, r)
        self.tree[node] = self.tree[node*2+1] ^ self.tree[node*2+2]

    def query(self, l, r, x):
        return self._query(0, self.l, self.r, l-1, r-1, x)

    def _query(self, node, l, r, ql, qr, x):
        if r < ql or l > qr:
            return 0
        
        if ql <= l and r <= qr:
            return self.tree[node] ^ x
        
        mid = (l + r) >> 1
        res1 = self._query(node*2+1, l, mid, ql, qr, x)
        res2 = self._query(node*2+2, mid+1, r, ql, qr, x)
        return res1 ^ res2
    

if __name__ == "__main__":
    n = int(input().strip())
    data = list(map(int, input().split()))
    st = SegmentTree(data)
    q = int(input().strip())
    for _ in range(q):
        x, l, r = map(int, input().split())
        print(st.query(l, r, x))
时间复杂度

该算法的时间复杂度约为 O(nlogn),其中 n 代表序列中元素的个数。

空间复杂度

该算法的空间复杂度约为 O(nlogn),其中 n 代表序列中元素的个数。