一种 trie + bfs 做法,求时间复杂度分析
查看原帖
一种 trie + bfs 做法,求时间复杂度分析
948133
SteveHans楼主2025/2/8 17:08

请大佬帮忙看看这个做法,已经 AC。主要思想就是贪心,如果有相异的位那就选择相异,没有就选相同位。这个做法应该(心虚)最坏情况下是直接遍历这个 trie,时间复杂度应该是 O(kn)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;
}
2025/2/8 17:08
加载中...