异或和 蓝桥杯2024python省赛 题解

异或和

题意

异或和 蓝桥杯2024python省赛 题解_第1张图片
经典的树上单点修改+子树求和的问题。那么我们首先可以想到构建出树的dfs序,将原本一棵树上的内容转化为一个数组。再由于异或运算和加法一样具有可逆性,所以使用树状数组维护即可。

然后由于树状数组维护的性质有限,每次只能额外异或一个数而不能直接进行赋值,所以我们保留好原数组,每次给单点赋值时,视为异或上“原来的值异或现在的值”就可以了。复杂度为 O(mlogn)。

附上python代码

import sys
from collections import Counter
from heapq import *
input = lambda: sys.stdin.readline().strip()
n, m = map(int, input().split())
a = [0] * (100000 + 10)
temp = list(map(int, input().split()))
a[1 : n + 1] = temp
e = [[] for _ in range(100000 + 5)]
for i in range(n - 1):
    x, y = map(int, input().split())
    e[x].append(y)
    e[y].append(x)
tr = [0] * (200000 + 101)
l = [0] * (200000 + 10)
r = [0] * (200000 + 10)
N = 200000 + 100
timestamp = 0

def dfs(u: int, fa: int):
    global timestamp
    timestamp += 1
    l[u] = timestamp
    for v in e[u]:
        if v != fa:
            dfs(v, u)
    timestamp += 1
    r[u] = timestamp


dfs(1, -1)


def lowbit(x):
    return x & -x


def add(x, k):
    i = x
    while i <= N:
        tr[i] ^= k
        i += lowbit(i)


def query(x):
    res, i = 0, x
    while i > 0:
        res ^= tr[i]
        i -= lowbit(i)
    return res


for i in range(1, n + 1):
    add(l[i], a[i])
for _ in range(m):
    p = list(map(int, input().split()))
    if p[0] == 1:
        x, y = p[1], p[2]
        add(l[x], a[x] ^ y)
        a[x] = y
    else:
        x = p[1]
        print(query(r[x]) ^ query(l[x] - 1))

你可能感兴趣的:(蓝桥杯,python,java,c++,算法,数据结构)