给定带边权的无根树,定义dis(u,v)
等于u到v简单路径上所有边的GCD,每次可以询问一个点集,会返回点集中所有点对的dis最大值,最后输出这棵树中,使得dis(u,v)
最大的u,v
。
(2<=n<=1e3 ,最多询问12次)
- 首先GCD具有只减不增的性质,最后答案就等价于输出边权最大的边的两个顶点。每次询问也是返回的最大边权。
- 看到询问次数,12,点只有1000个,说明主体算法肯定是二分了。
- 我们首先可以询问所有的点,返回的一定是最大边权W。
- 我们想到,能不能把所有的边分成两部分,左边右边各询问一次,看看最大边权W在哪边,这两部分相当于把树分成了两个连通块,所有的边仍然是有序的。
- 我们可以用边的dfs序,在这个序列上,边始终是按访问顺序排列,可以进行二分。每次二分相当于把1个连通块分成了两个。
#include<bits/stdc++.h>
using namespace std;
//#pragma GCC optimize(2)
#define ull unsigned long long
#define ll long long
#define pii pair<int, int>
const int maxn = 1e3 + 10;
const ll mod = 998244353;
const ll inf = (ll)4e16+5;
const int INF = 1e9 + 7;
const double pi = acos(-1.0);
ll inv(ll b)