当前位置:   article > 正文

蓝桥杯第14届省赛Python B组 I题 异或和 (25分)_蓝桥pyhton省赛试题i: 异或和

蓝桥pyhton省赛试题i: 异或和

问题描述

        给一颗含有n个节点的有根树,根节点为1,编号为i的点有点权ai ( i ∈[1,n])。现在有两种操作,格式如下:

        1 x y : 该操作将点x的点权改为y 。

        2 x : 该操作表示查询以结点x 为根的子树内的所有点的点权的异或和。

        现有长度为m 的操作序列,请对于每个第二类操作给出正确的结果 。

输入格式

         输入的第一行包含两给正整数n,m,用一个空格分隔。

        第二行包含 n 个整数a1,a2,...,an,相邻整数之间使用一个空格分隔。

        接下来 n − 1 行,每行包含两个正整数 ui,vi ,表示结点 ui 和 v 之间有一条边。

        接下来 m 行,每行包含一个操作

输出格式

        输出若干行,每行对应一个查询操作的答案。

样例输入

4 4

1 2 3 4

1 2

1 3

2 4

2 1

1 1 0

2 1

2 2

样例输出

4

5

6

测评用例规模与约定

        对于30%的测评用例, n,n<=1000;

        对于所有测评用例, 1<=n,m<=100000, 0<=ai, y<=100000, 1<= ui,vi,x<=n。

概念引入

        首先要了解两个概念,一个是子树,一个是异或操作。

        1.题目中只是说是ui和vi之间存在一条边,没有明确指出哪个是父节点,哪个是子节点,这就产生了歧义,在子树划分的时候。由问题描述中的根节点为1,可以推断出,在所有的边中,编号较小的节点是父节点,编号较大的是子节点。(这里有点不妥,应该设置visit数组,根据先后进入顺序确定为父节点还是子节点,懒得改)
        2.异或操作的性质。异或逻辑的关系是:当AB不同时,输出P=1;当AB相同时,输出P=0。在python中可以通过^操作符实现。异或操作的几个性质如下:

A^A=0;  

A^0=A;

A^B^A=B^A^A=B^0=B;

思路讲解

        1. 定义两个字典,child_d,f_d,分别记录子节点和父节点的信息;定义一个数组sum_,存储编号为i的节点的子树的异或和。

  1. n,m = map(int,input().split())
  2. num = list(map(int,input().split()))
  3. num.insert(0,0)
  4. child_d = dict()
  5. f_d = dict()
  6. sum_ = [i for i in num]

        2.dfs搜索child_d,初始化异或和数组sum_。

  1. def dfs(n):
  2. if n not in child_d:
  3. return num[n]
  4. for i in child_d[n]:
  5. sum_[n] ^=dfs(i)
  6. return sum_[n]
  7. _ = dfs(1)

        3.对于输入的第一类操作,即返回sum_[i]即可。

        4.对于第二类的修改操作,维护sum_是整道题的关键。

             因为异或和数组储存的是子树的所有数一起的异或和,所以如果修改节点v的值,那么v和v的所有祖先节点(即父节点和父节点的父节点等等)的异或和数组sum_的值都会改变。
             之前维护的记录父节点的字典就用得到了,修改一次节点的值之后,要循环更新所有祖先节点的异或和的值。

由之前提到的性质 

        A^B^A=B^A^A=B^0=B;

可以得到,

将节点v的值从n1改到n2,节点的异或和s只需要与n1,n2一起进行异或操作即可完成更新。

如: 当前节点的权值为4,异或和为

        s = 4^3^2^1,

进行第二类操作将节点的值改为3

修改后的节点的异或和为

        s2 = 3^3^2^1

将s与n1,n2一起进行异或操作,得

        s3 = s^4^3 = 4^3^2^1^4^3 = 4^4^3^3^2^1 = 3^3^2^1 = s2

  1. for i in range(m):
  2. s = list(map(int,input().split()))
  3. if s[0]==1:
  4. temp =s[1]
  5. val = s[2]^num[temp]
  6. num[temp] = s[2]
  7. sum_[temp]^= val
  8. while temp in f_d:
  9. temp = f_d[temp]
  10. sum_[temp]^= val
  11. else:
  12. s2.append(sum_[s[1]])

  

完整代码

        

  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Wed Nov 1 11:49:51 2023
  4. @author: 犹豫
  5. """
  6. n,m = map(int,input().split())
  7. num = list(map(int,input().split()))
  8. num.insert(0,0)
  9. child_d = dict()
  10. f_d = dict()
  11. sum_ = [i for i in num]
  12. for i in range(n-1):
  13. v,u = map(int,input().split())
  14. if v>u:
  15. v,u =u,v
  16. if v in child_d:
  17. child_d[v].append(u)
  18. else:
  19. child_d[v]=[u]
  20. f_d[u]=v
  21. def dfs(n):
  22. if n not in child_d:
  23. return num[n]
  24. for i in child_d[n]:
  25. sum_[n] ^=dfs(i)
  26. return sum_[n]
  27. _ = dfs(1)
  28. s2=[]
  29. for i in range(m):
  30. s = list(map(int,input().split()))
  31. if s[0]==1:
  32. temp =s[1]
  33. val = s[2]^num[temp]
  34. num[temp] = s[2]
  35. sum_[temp]^= val
  36. while temp in f_d:
  37. temp = f_d[temp]
  38. sum_[temp]^= val
  39. else:
  40. s2.append(sum_[s[1]])
  41. for i in s2:
  42. print(i)

结果

    官网AC

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/1013538
推荐阅读
相关标签
  

闽ICP备14008679号