1. 程式人生 > 實用技巧 >【資料結構】01Trie

【資料結構】01Trie

https://codeforces.ml/contest/888/problem/G

    struct TrieNode {
        int cnt;
        int num;
        int nxt[2];

        void Init() {
            cnt = 0;
            num = 0;
            memset(nxt, 0, sizeof(nxt));
        }
    };

    struct Trie {
        static const int MAXN = 200000;
        TrieNode tn[MAXN * 32 + 5];
        int root, top;

        int NewNode() {
            tn[++top].Init();
            return top;
        }

        void Init() {
            top = 0;
            root = NewNode();
        }

        void Insert(int a) {
            int cur = root;
            ++tn[cur].cnt;
            for(int i = 30; i >= 0; --i) {
                int &nxt = tn[cur].nxt[a >> i & 1];
                if(!nxt)
                    nxt = NewNode();
                tn[nxt].num = tn[cur].num | (a & (1 << i));
                cur = nxt;
                ++tn[cur].cnt;
            }
        }

        ll help(int cur, int Rnum) {
            if(tn[cur].nxt[0] == 0 && tn[cur].nxt[1] == 0)
                return tn[cur].num ^ Rnum;
            if(tn[cur].nxt[0] == 0)
                return help(tn[cur].nxt[1], Rnum);
            if(tn[cur].nxt[1] == 0)
                return help(tn[cur].nxt[0], Rnum);
            if((tn[tn[cur].nxt[0]].num ^ Rnum) < (tn[tn[cur].nxt[1]].num ^ Rnum))
                return help(tn[cur].nxt[0], Rnum);
            else
                return help(tn[cur].nxt[1], Rnum);
        }

        ll count(int cur, int Lroot) {
            if(tn[cur].nxt[0] == 0 && tn[cur].nxt[1] == 0)
                return help(Lroot, tn[cur].num);
            if(tn[cur].nxt[0] == 0)
                return count(tn[cur].nxt[1], Lroot);
            if(tn[cur].nxt[1] == 0)
                return count(tn[cur].nxt[0], Lroot);
            return min(count(tn[cur].nxt[1], Lroot), count(tn[cur].nxt[0], Lroot));
        }

        ll calc(int cur) {
            if(cur == 0 || tn[cur].cnt <= 1)
                return 0;
            if(tn[cur].nxt[0] == 0 && tn[cur].nxt[1] == 0)
                return 0;
            if(tn[cur].nxt[0] == 0)
                return calc(tn[cur].nxt[1]);
            if(tn[cur].nxt[1] == 0)
                return calc(tn[cur].nxt[0]);
            ll res = calc(tn[cur].nxt[0]) + calc(tn[cur].nxt[1]);
            ll tmp = count(tn[cur].nxt[1], tn[cur].nxt[0]);
            return res + tmp;
        }

    } trie;