How Many Answers Are Wrong
题目大意:给定一些区间的和,如果发现与前面矛盾就认为是假话.
带权并查集判错的经典例题,直到如今才学会.
这个算法实在是太经典了,所以我要十分详细的把自己掌握的写出来,方便自己和后人查阅,在此感谢这篇题解的详细指导
为什么要用并查集?
对于通常的并查集例题,都是一开始每个元素构成一个单元素集合.其后不断合并.
与这题联系起来便十分抽象,因为我们要判断真假,怎么判?肯定是比较.怎么比?跟谁比?比什么?
怎么比:假设当前输入a,b,v与之前所有输入的a,b,v相比,存在a=a,b=b,v=v,则说明没错,
但是一定能找到吗?如果找不到,说明一定是错吗?显然不是,因此不能这么比.
要想比,首先得找一个基准值,如果(a到c的距离) - (b到c的距离) == v,说明正确,解决了跟谁比,怎么比.
具体思路:
给出一个闭区间\([a,b]\),转化为:\((a-1,b]\),因为半开半闭区间有个性质:\((a,b] + (b,c] = (a,c]\)
再来考虑如何解读一条信息:a,b,v?可以解读为:a与b有关系,关系的权值是一个v
但是如何求ac,bc之间的距离,首先保证a,b的基准值都是c才可以,怎么把a,c的基准值都为c?
考虑到并查集是用来记录联通关系的.
如果当前两个点的基准值不一样,说明本条信息一定是正确的,因为无法根据其现有数据推算正假,于是认其为真.之后合并当前信息,为下一次查询做准备.
如果当前两个点的基准值一样,那么说明两个点之间的距离可以通过之前的计算出来,则比较,相等没事,不相等的话计数器加1
更清晰的话,有如下图表示:
用sum[k]表示k到k的基准点之间距离.
如果想合并a,b,最终目的是求a,b到共同基准值的距离.
首先求出a,b的祖先,然后比较x,y默认x认y为爹(a的祖先认b的祖先为爹)
所以a的祖先变成了y,x的祖先变成了y.
其中显然: \[ sum[x] = sum[b] + v - sum[a] \]
\(sum[b]+v\)是a到y的距离,减去a到x的距离\(sum[x]\)剩下的就是x到y的距离.(这里的区间都是左闭右开)
至此,代码与思路就都十分清晰了.
代码如下:
1 |
|
后记:
并查集经典应用