
题目考点
这道题主要考的是这几个知识点:
set集合- 集合的几种原地修改操作
intersection_update()update()symmetric_difference_update()difference_update()
- 输入处理
- 循环读取多组操作
- 最后对集合元素求和
sum()
这道题本质上不是在考复杂算法,而是在考你能不能:
- 把输入一组一组读出来
- 看懂“操作名 + 另一个集合”
- 对原集合
A进行对应修改
所以核心不是“算”,而是“按要求改集合”。
审题
输入是什么
题目会给你:
- 第一行:集合
A的元素个数 - 第二行:集合
A的所有元素 - 第三行:整数
N,表示接下来有几次操作 - 接下来每次操作占两行:
- 第一行:操作名 和 另一个集合的长度
- 第二行:另一个集合的元素
输出是什么
输出经过这 N 次操作之后,集合 A 中所有元素的和。
题目要求我们做什么
题目不是让你新建很多结果,而是让你不断修改原来的集合 A。
也就是说:
- 先有一个初始集合
A - 然后对它执行若干次集合操作
- 最后输出
sum(A)
容易忽略的点
1. 每次操作都会直接修改 A
比如:
A.intersection_update(B)
这不是返回一个新集合,而是直接把 A 改掉。
2. 每次操作第一行里的“长度”通常不用手动参与计算
例如:
intersection_update 10
这里的 10 只是告诉你下一行有 10 个数。
实际写程序时,我们通常直接把下一行读成一个集合就行,不一定非要用这个 10。
3. 集合是无序的
所以不要想着按位置去处理,集合题的重点是“有没有这个元素”。
思路提示
先不要急着写代码,先把题目流程想清楚。
第一步:读入初始集合 A
题目先给出 A 的元素个数,再给出元素列表。
我们把第二行转成集合即可。
第二步:读入操作次数 N
说明接下来要循环 N 次,每次都要处理一组“操作”。
第三步:每次操作分两部分读
先读操作名,比如:
intersection_updateupdatesymmetric_difference_updatedifference_update
再读下一行,把它变成另一个集合 B。
第四步:根据操作名,修改 A
看到什么操作名,就调用对应的方法。
第五步:全部做完后,输出 sum(A)
完整设计思路
这道题最好的做法,是把它理解成“按命令执行”。
第 1 步:建立集合 A
比如输入这一行:
1 2 3 4 5
我们可以写:
A = set(map(int, input().split()))
这样就把这一行整数转成集合了。
注意前面那一行元素个数:
int(input())
这一行通常只是题目格式要求,很多时候读了但不一定非要使用。
第 2 步:读取操作次数 N
N = int(input())
表示后面要做 N 次集合变换。
第 3 步:每次先读“操作名”
例如这一行:
intersection_update 10
可以这样拆开:
operation, _ = input().split()
这里为什么第二个用 _?
因为这一行有两个东西:
operation:操作名10:另一个集合的长度
但这个长度对我们后面处理并不是必须的,所以常用 _ 表示“读进来了,但暂时不用”。
第 4 步:读取另一个集合
下一行就是这个操作要用到的集合,比如:
2 3 5 6 8 9 1 4 7 11
可以写成:
B = set(map(int, input().split()))
第 5 步:根据操作名执行对应方法
这是整道题最关键的部分。
情况 1:交集更新
A.intersection_update(B)
意思是:A 只保留和 B 都有的元素。
情况 2:并集更新
A.update(B)
意思是:把 B 的元素加入到 A 中。
情况 3:对称差更新
A.symmetric_difference_update(B)
意思是:保留“只在其中一个集合里出现”的元素。
也可以理解成:
- 两边都有的删掉
- 只在一边有的保留
情况 4:差集更新
A.difference_update(B)
意思是:从 A 里删掉那些也在 B 中的元素。
第 6 步:最后求和
所有操作结束后:
print(sum(A))
代码实现
下面给你一个适合初学者、结构很清楚的版本。
# 读入集合 A 的元素个数(这题里主要是配合输入格式,后面不一定要用)
n = int(input())
# 读入集合 A
A = set(map(int, input().split()))
# 操作次数
N = int(input())
for _ in range(N):
# 读入操作名和另一个集合的长度
operation, length = input().split()
# 读入另一个集合
B = set(map(int, input().split()))
# 根据操作名执行对应操作
if operation == "intersection_update":
A.intersection_update(B)
elif operation == "update":
A.update(B)
elif operation == "symmetric_difference_update":
A.symmetric_difference_update(B)
elif operation == "difference_update":
A.difference_update(B)
# 输出最终集合元素之和
print(sum(A))
运行演示
我们就用题目里的样例来手动走一遍。
初始集合
A = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 24, 52}
第一次操作
intersection_update
B = {2, 3, 5, 6, 8, 9, 1, 4, 7, 11}
交集更新后,A 只保留共同元素:
A = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11}
第二次操作
update
B = {55, 66}
把 B 加入 A:
A = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 55, 66}
第三次操作
symmetric_difference_update
B = {22, 7, 35, 62, 58}
对称差更新规则是:
- 两边都有的删掉
- 只在一边有的保留
因为 7 在两边都有,所以删掉。22, 35, 62, 58 原来不在 A 中,所以加进去。
结果:
A = {1, 2, 3, 4, 5, 6, 8, 9, 11, 22, 35, 55, 58, 62, 66}
第四次操作
difference_update
B = {11, 22, 35, 55, 58, 62, 66}
从 A 中删掉这些元素:
A = {1, 2, 3, 4, 5, 6, 8, 9}
最后求和
1 + 2 + 3 + 4 + 5 + 6 + 8 + 9 = 38
所以输出:
38
方法总结
以后遇到这种题,你可以按这个模板去识别。
看到这些关键词,就要想到集合题
setupdateintersectiondifferencesymmetric_difference
做题步骤固定为
1. 先把原集合读出来
A = set(map(int, input().split()))
2. 再循环读命令
每次命令一般分两行:
- 第一行:操作名
- 第二行:另一个集合
3. 用 if/elif 分发操作
这一步本质就是“命令匹配”。
4. 最后按题目要求输出
这题是:
print(sum(A))
易错点提醒
易错点 1:把集合写成列表
这题必须用 set,因为操作本来就是集合操作。
如果你用 list,会非常麻烦,而且不符合题目本意。
易错点 2:忘了把输入转成整数
如果你写成:
set(input().split())
得到的是字符串集合,不是整数集合。
要写成:
set(map(int, input().split()))
易错点 3:把方法名字写错
比如:
intersection_updatesymmetric_difference_updatedifference_update
这些名字都比较长,拼写容易错。
易错点 4:误以为这些方法有返回值
这些方法是“原地修改”,不要写成:
A = A.update(B)
因为这样很容易出问题。
正确写法就是直接:
A.update(B)
补充说明:为什么第一行的元素个数经常没用上
题目第一行给你:
16
第二行给你:
1 2 3 4 ...
从严谨上说,第一行是在告诉你第二行应该有多少个数。
但在 Python 里,我们通常直接把第二行整行读入再拆分:
A = set(map(int, input().split()))
所以很多时候这个数量只是“输入格式说明”,程序里不一定非要用它控制读取。
这在很多刷题题目里都很常见。
练习
下面给你一道同类型的小练习,先自己试着做。
题目
已知:
A = {1, 2, 3, 4, 5}
依次执行下面三步操作:
update({6, 7})difference_update({2, 4, 6})symmetric_difference_update({1, 3, 8})
问最后集合 A 的元素之和是多少?
提示
你可以按这三步手动模拟:
- 先把新元素加进去
- 再删掉指定元素
- 最后做对称差:共同的删掉,只出现一次的保留



