对于线段树合并+并查集的做法,请注意并查集是否应用启发式合并:
例如:
void bing(int a, int b) { int x = find(a), y = find(b); if(x == y) return; if(siz[x] < siz[y]) swap(x, y); siz[x] += siz[y]; father[y] = x; }
这就是启发式合并并查集。
而这种并查集,对于这种合并会出现问题:
rt[d1.find(x)] = merge(rt[d1.find(x)], rt[d1.find(y)], 1, n); d1.bing(x, y);
因为启发式合并可能会将合并后的这个集合的代表变为 y 而非希望的 x。
解决方法:删去 if(siz[x] < siz[y]) swap(x, y);
或将上面的合并改为 rt[d1.find(x)] = rt[d1.find(y)] = merge(rt[d1.find(x)], rt[d1.find(y)], 1, n); d1.bing(x, y);