Cod sursa(job #3172169)

Utilizator Dragono63Stanciu Rares Stefan Dragono63 Data 20 noiembrie 2023 11:33:38
Problema Cowfood Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.69 kb
#include <bits/stdc++.h>
#pragma GCC optimize("O3") 

using namespace std;
 
const int NMAX = 2e5 + 5;
const int NRMAX = (1LL << 31) - 1;
ifstream f("xor-mst.in");
ofstream g("xor-mst.out");
 
int N;
bool bit;
long long ans;
int cnt_culori, rasp;
int a[NMAX], culori[NMAX];
 
struct Trie
{
    int cnt;
    Trie* fii[2];
};
 
struct edge
{
    int x, y, cost;
 
    edge ()
    {
        x = y = -1;
        cost = NRMAX;
    }
 
    edge (int _x, int _y, int _cost)
    {
        x = _x;
        y = _y;
        cost = _cost;
    }
} min_muchie[NMAX];
 
set < pair <int, int> > muchii_adaugate;
vector <int> noduri_cu[NMAX];
vector < int > apm[NMAX];
 
set <pair <int, int> > s;
 
Trie *trie = new Trie();
inline void dfs(int nod)
{
    if (culori[nod]) return;
 
    culori[nod] = cnt_culori;
    noduri_cu[cnt_culori].push_back(nod);
    for (auto u: apm[nod])
    {
        if (!culori[u])
            dfs(u);
    }
}
 
 
void add(Trie *trie, int x)
{
    Trie *curr = trie;
    for (int i = 30 ; i >= 0 ; -- i)
    {
        bit = (x & (1 << i));

        if (curr->fii[bit] == NULL)
            curr->fii[bit] = new Trie();
        
        curr->fii[bit]->cnt ++;
        curr = curr->fii[bit];
    }
}
 
void scoate(Trie *trie, int x)
{
    Trie* curr = trie;

    for (int i = 30 ; i >= 0 ; -- i)
    {
        bit = (x & (1 << i));
        curr->fii[bit]->cnt --;
        curr = curr->fii[bit];
    }
}
 
int get_min(Trie *trie, int x, int k)
{
    int rasp = 0;
    Trie* curr = trie;
    for (int i = 30 ; i >= 0 ; -- i)
    {
        bit = (x & (1 << i));

        if (curr->fii[bit] != NULL && curr->fii[bit]->cnt > 0)
            curr = curr->fii[bit];
        else
        {
            curr = curr->fii[!bit];
            rasp = rasp + (1 << i);
        }
    }
    
    return rasp;
}
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
 
    cin >> N;
    for (int i = 1 ; i <= N ; ++ i)
    {
        cin >> a[i];
        add(trie, a[i]);
        s.insert({a[i], i});
    }
 
    int rasp, val_gasita;
    edge muc;
    pair <int, int> p;
    for (int k = 0 ; k < 50 ; ++ k)
    {
        for (int i = 1 ; i <= N ; ++ i)
            culori[i] = 0;
 
        cnt_culori = 0;
        for (int i = 1 ; i <= N ; ++ i)
        {
            if (!culori[i])
            {
                ++ cnt_culori;
                noduri_cu[cnt_culori].clear();
                dfs(i);
            }
        }
 
        if (cnt_culori == 1)
            break;
 
        for (int i = 1 ; i <= cnt_culori ; ++ i)
        {
            min_muchie[i] = edge{};
 
            for (auto u: noduri_cu[i])
            {
                auto it = s.find({a[u], u});
                s.erase(it);
                scoate(trie, a[u]);
            }
 
            for (auto u: noduri_cu[i])
            {
                rasp = get_min(trie, a[u], 29);
                if (rasp > min_muchie[i].cost) continue;
                val_gasita = (a[u] ^ rasp);
 
                auto it = s.lower_bound({val_gasita, 0});
                p = *it;
                
                min_muchie[i] = edge{u, p.second, rasp};
            }
 
            for (auto u: noduri_cu[i])
            {
                add(trie, a[u]);
                s.insert({a[u], u});
            }
        }
 
        for (int i = 1 ; i <= cnt_culori ; ++ i)
        {
            muc = min_muchie[i];
            p.first = min(muc.x, muc.y);
            p.second = max(muc.x, muc.y);
 
            if (muchii_adaugate.find(p) != muchii_adaugate.end())
                continue;
 
            muchii_adaugate.insert(p);
            apm[muc.x].push_back(muc.y);
            apm[muc.y].push_back(muc.x);
            ans += 1LL * muc.cost;
        }
    }
 
    cout << ans;
    return 0;
}