题意
原题链接
给定一个 \(n\) 个点的无向图,你可以进行不超过 \(max\_ops\) 次查询操作 \(\text{Connected}(x,a, b)\),每次操作可以查询在版本 \(x\) 中,\(a,b\) 两个点之间是否连通,若连通,则返回当前版本号,否则新建一个版本,在该新版本中将这两个点之间连一条边,并返回新版本的版本号。要求构造出一个无向图,使得对于任意两个点,这两个点之间的连通情况与原版本中这两个点之间的连通情况相同。
赛时 并查集 65PTS
最简单的算法即为 \(O(n^2)\) 的枚举。
事实上,如果两个点已经连通,就没有必要再次查询了;同理,如果一个的连通的任意一个点和另一个点不连通,也没有必要再次查询了。
因此,使用并查集维护连通性,并记录某一点不连通的所有点即可。
赛后
赛时的代码通过改变枚举顺序,可以 AC 此题。但仍有被卡可能。
类似于并查集的思想,我们可以记录与点 \(i\) 连通的最小的点 \(f_i\),在输出时,我们只需要将 \(f_i\) 与 \(i\) 连边即可(\(f_i \ne i\))
显然,每个点有两种情况:
- 点 \(i\) 不与 \(1\sim i-1\) 的任意点相连通,单独成为一个连通块
- 点 \(i\) 与 \(1\sim i-1\) 中的至少一点相连通
我们可以记录点 \(1 \sim i\) 连通的最小的版本号 \(rt_i\),显然,\(rt_i = \text{Connected}(rt_{i-1}, 1, i)\)。
若 \(rt_i \ne rt_{i-1}\),由于版本 \(rt_{i-1}\) 中,\(1\sim i-1\) 已经连接,因此 \(i\) 单独成为一个连通块,即情况 \(1\)。
否则,\(i\) 不会单独成为一个连通块,即情况 \(2\)。
对于情况 \(1\),由定义,显然可得 \(f_i = i\);
对于情况 \(2\),在 \(rt\) 构成的版本序列中,可以分为两段,前一段中,\(i\) 不与 \(1\sim i-1\) 连通,此时任取这一段中的一个 \(rt_j\),都有 \(\text{Connected}(rt_j, j, i) \ne rt_j\);后一段中, \(i\) 与 \(1 \sim i-1\) 连通,此时任取这一段中的一个 \(rt_j\),都有 \(\text{Connected}(rt_j, j, i) = rt_j\)。
由此可得,在后一段中的第一个 \(rt_j\) 即为 \(i\) 与 \(1\sim i-1\) 连通的第一个版本,因此,\(f_i = j\)。显然我们可以使用二分通过 \(\log n\) 次查询找到这个 \(j\);
不过如果这样直接二分的话,对于特殊数据,可能会略微超出一点。因此,我们还需要进行一点优化:因为 \(f_i\) 是与 \(i\) 连通的编号最小点,因此,对于任意两点 \(i,j\),其中 \(f_i=i,f_j\ne j\),若 \(f_i=f_j\),则一定存在 \(i<j\)。因此,我们不需要二分整个 \(rt\),只需要二分其中所有下标 \(i\) 满足 \(f_i = i\) 的版本即可。
代码
#include "akai.h"
using namespace std;
const int N = 205;
int f[N], rt[N];
int s[N], idx = 0;
void ToyDesign(int n, int max_ops){
rt[1] = 0;
f[1] = 1;
s[ ++ idx] = 1;
for (int i = 2; i <= n; i ++ ){
rt[i] = Connected(rt[i - 1], i - 1, i);
if (rt[i - 1] != rt[i]) f[i] = i, s[ ++ idx] = i;
else {
int l = 1, r = idx;
while (l < r){
int mid = (l + r) >> 1;
if (Connected(rt[s[mid]], s[mid], i) == rt[s[mid]]) r = mid;
else l = mid + 1;
}
f[i] = s[l];
}
}
vector<pair<int, int>> result;
for (int i = 1; i <= n; i ++ )
if (f[i] != i) result.push_back({i, f[i]});
DescribeDesign(result);
}
标签:rt,连通,int,luoguP9323,mid,玩具,版本,lnsyoj2234,sim
From: https://www.cnblogs.com/XiaoJuRuoUP/p/-/lnsyoj2234_luoguP9323