请大佬帮忙看看这个做法,已经 AC。主要思想就是贪心,如果有相异的位那就选择相异,没有就选相同位。这个做法应该(心虚)最坏情况下是直接遍历这个 trie,时间复杂度应该是 O(kn) 的。但是我觉得这个的常数应该比大家用的做法要小,因为尽量排除掉了不可能的答案。这份代码虽然在洛谷是与大众做法时间差不了多少,但是在 ACWing 就明显慢了。求一个比较严谨的时间复杂度分析(当然也有可能是我写得常数比较大),或者大家也可以出出 Hack。(☆▽☆)
#include <iostream>
#include <queue>
using namespace std;
const int N = 1e5 + 10, M = N * 31;
int n;
int a[N];
int tr[M][2], idx;
void insert(int x)
{
int p = 0;
for (int i = 30; i >= 0; i -- )
{
int v = (x >> i & 1);
if (!tr[p][v]) tr[p][v] = ++ idx;
p = tr[p][v];
}
}
struct State
{
int p, q, res, bit;
};
State get_next(State t, int pv, int qv)
{
int p = t.p, q = t.q, res = t.res, i = t.bit;
int ne_p = tr[p][pv], ne_q = tr[q][qv];
if (pv != qv) res ^= 1 << i;
t = {ne_p, ne_q, res, i - 1};
return t;
}
int bfs()
{
queue<State> q;
q.push({0, 0, 0, 30});
int res = 0;
while (q.size())
{
State t = q.front(); q.pop();
res = max(res, t.res);
int p0 = tr[t.p][0], p1 = tr[t.p][1], q0 = tr[t.q][0], q1 = tr[t.q][1];
if ((p0 && q1) || (p1 && q0))
{
if (p0 && q1) q.push(get_next(t, 0, 1));
if (p1 && q0) q.push(get_next(t, 1, 0));
}
else
{
if (p1 && q1) q.push(get_next(t, 1, 1));
if (p0 && q0) q.push(get_next(t, 0, 0));
}
}
return res;
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i ++ )
{
cin >> a[i];
insert(a[i]);
}
printf("%d\n", bfs());
return 0;
}