题目描述
现在有n个数,X0,X1,…,Xn-1,你并不知道这n个数的大小,然后接下来有Q个询问,询问的格式如下
1) I p v, 告诉你 Xp = v
2) I p q v, 告诉你 Xp ^ Xq = v
3) Q k Xi, Xi+1, ..,Xi+k-1, 让你求Xi ^ Xi+1 ^..^ Xi+k-1的值
如果输入的第i个I条件和前面已知的冲突,则输出The first %d facts is conflicting.
,并不输出后面的询问。
如果Q条件可以求取则输出对应的值,否则输出I don't know
。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3234
思路
已知A^B
,B^C
, 则A^C
唯一确定。这种关系是带权并查集的典型应用。
定义 f[x]为x的根节点, w[x]表示和父节点异或值。
如何处理询问1?我构造一个节点n
,其值为0,则任一节点p其值为v等价于节点p和节点n异或值为v,从而将询问1转换为询问2,即I p v to I p n v
。
对于询问Q,首先求出k个数对应多少个集合以及集合的个数,如果当某一集合的节点点既不为n且其元素个数为奇数时,则无法求出结果。因为f[a] = f[b] = r, a ^ b = a ^ (c ^ c) ^ b = (a ^ c) ^ (b ^ c) = w[a] ^ w[b].
有一个WA点,在并查集merge的过程中要始终保持节点n作为根节点。否则询问Q的时候会判断错误。
AC代码
#include
#include
#include >
#include
总结
- sscanf的应用,通过sscanf的返回值可以知道其正确读取了多少个数。
- 虚拟节点的设立从而将询问1转化为询问2。