📌  相关文章
📜  在二进制数组中将范围更新查询与1进行XOR。(1)

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

在二进制数组中将范围更新查询与1进行XOR。

在某些算法问题中,您可能需要对二进制数组进行范围更新查询并对结果与1进行XOR操作。在这种情况下,您可以使用线段树或树状数组,这两种数据结构都可以实现快速查询和更新。

线段树

线段树是一种树形数据结构,常用于动态数组或静态数组的查询和更新。每个线段树节点是一个范围,并且每个节点都代表它的子节点的并集。因此,您可以在O(log n)时间内查询和更新任何范围。

在本问题中,您可以使用线段树将每个元素的值从0或1提取到它的相应节点,并在每个节点上维护一个XOR操作值。更新操作末尾节点的XOR值,然后从根节点向下遍历并将所有范围覆盖的节点的XOR值进行相应的操作。查询操作仅涉及根节点,并对其进行相应的操作。

class SegmentTree:
    def __init__(self, arr: List[int]):
        n = len(arr)
        self.arr = arr
        self.tree = [0] * (4 * n)
        self.lazy = [0] * (4 * n)

    def build(self, l: int, r: int, i: int) -> None:
        if l == r:
            self.tree[i] = self.arr[l]
        else:
            mid = (l + r) // 2
            self.build(l, mid, 2 * i + 1)
            self.build(mid + 1, r, 2 * i + 2)
            self.tree[i] = self.tree[2 * i + 1] ^ self.tree[2 * i + 2]

    def get_xor(self, l: int, r: int, i: int, x: int, y: int) -> int:
        if x > r or y < l:
            return 0
        if x <= l and y >= r:
            return self.tree[i] ^ self.lazy[i]
        mid = (l + r) // 2
        self.tree[i * 2 + 1] ^= self.lazy[i]
        self.tree[i * 2 + 2] ^= self.lazy[i]
        self.lazy[i * 2 + 1] ^= self.lazy[i]
        self.lazy[i * 2 + 2] ^= self.lazy[i]
        self.lazy[i] = 0
        return self.get_xor(l, mid, i * 2 + 1, x, y) ^ self.get_xor(mid + 1, r, i * 2 + 2, x, y)

    def update(self, l: int, r: int, i: int, x: int, y: int, val: int) -> None:
        if self.lazy[i]:
            self.tree[i] ^= self.lazy[i]
            if l != r:
                self.lazy[2*i + 1] ^= self.lazy[i]
                self.lazy[2*i + 2] ^= self.lazy[i]
            self.lazy[i] = 0
        if y < l or x > r:
            return
        if x <= l and r <= y:
            self.tree[i] ^= val
            if l != r:
                self.lazy[2 * i + 1] ^= val
                self.lazy[2 * i + 2] ^= val
            return
        mid = (l + r) // 2
        self.update(l, mid, i * 2 + 1, x, y, val)
        self.update(mid + 1, r, i * 2 + 2, x, y, val)
        self.tree[i] = self.tree[i * 2 + 1] ^ self.tree[i * 2 + 2]
树状数组

树状数组是一种数据结构,常用于累积和查询和范围更新操作。和线段树一样,其实现通常是基于递归和分治技术。

在本问题中,您可以使用树状数组来实现快速更新操作。每当您更新数组中的元素时,您可以使用树状数组来查询该元素的前缀和并使用该差异作为更新值。这样,您就可以使用O(log n)时间更新元素值。

class FenwickTree:
    def __init__(self, arr: List[int]):
        self.n = len(arr)
        self.tree = [0] * (self.n + 1)
        for i in range(self.n):
            self.update(i + 1, i + 1, arr[i])

    def update(self, x: int, y: int, val: int) -> None:
        self.add(x, val)
        self.add(y + 1, -val)

    def add(self, idx: int, val: int) -> None:
        while idx <= self.n:
            self.tree[idx] ^= val
            idx += idx & -idx

    def query(self, x: int) -> int:
        res = 0
        while x > 0:
            res ^= self.tree[x]
            x -= x & -x
        return res

无论您使用线段树还是树状数组,您都可以在O(log n)时间内更新数组中的任何范围,并从中查询任何元素的值与1的异或结果。