제출 #385055

#제출 시각아이디문제언어결과실행 시간메모리
385055thecodingwizardČVENK (COI15_cvenk)C++11
38 / 100
3088 ms281192 KiB
#include <bits/stdc++.h>

using namespace std;

using ll = long long;
#define ii pair<ll, ll>
#define f first
#define s second
#define pb push_back
#define mp make_pair
#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()
#define F0R(i, n) for (int i = 0; i < n; i++)
#define FOR(i, a, b) for (int i = a; i < b; i++)
#define inf 1000000010

int n; 
vector<ii> A;

void clean(ii &a, ii &b) {
    for (int i = 30; ~i; i--) {
        if ((a.f & (1 << i)) && (b.f & (1 << i))) {
            a.f ^= (1 << i);
            b.f ^= (1 << i);
        } else if ((a.s & (1 << i)) && (b.s & (1 << i))) {
            a.s ^= (1 << i);
            b.s ^= (1 << i);
        } else if ((a.f & (1 << i)) || (b.f & (1 << i)) || (a.s & (1 << i)) || (b.s & (1 << i))) {
            break;
        }
    }
}
 
// true if left, false if up
// second number is distance from that axis
pair<bool, ll> calc(ii x) {
    int dir = -1;
    ll dist = 0;
    for (int i = 30; ~i; i--) {
        int curDir = -1;
        if (x.f & (1 << i)) {
            curDir = 1;
        } else if (x.s & (1 << i)) {
            curDir = 0;
        }
        if (dir == -1) dir = curDir;
        if (curDir != -1 && curDir != dir) break;
        if (curDir != -1) dist += (1 << i);
    }
    return make_pair(dir, dist);
}

ll solveSimple(ii a, ii b) {
    clean(a, b);
    pair<bool, ll> res = calc(a), res2 = calc(b);
     
    ll ans = a.f+a.s+b.f+b.s;
    if (res.f == res2.f) {
        ans -= 2*min(res.s, res2.s);
    }

    return ans;
}

int ctr = 1;
struct node {
    node *down = nullptr, *right = nullptr, *stay = nullptr;
    ll numNodes = 0, moveUpCost = 0;
    int id = 0;
    int cost = 0;
    string path = "";
} root;

ll getMoveUpCost(ii x, int i) {
    ll c = 0;
    while (i >= 0) {
        if ((x.f & (1 << i)) || (x.s & (1 << i))) c += (1 << i);
        i--;
    }
    return c;
}

void add(ii x, int i, node *n) {
    n->cost = 1 << (i+1);
    n->numNodes++;
    if (i < 0) return;

    node *next = nullptr;
    if (x.f & (1 << i)) {
        if (n->down == nullptr) {
            n->down = new node;
            n->down->id = ctr++;
            n->down->path = n->path + "D";
        }
        next = n->down;
    } else if (x.s & (1 << i)) {
        if (n->right == nullptr) {
            n->right = new node;
            n->right->id = ctr++;
            n->right->path = n->path + "R";
        }
        next = n->right;
    } else {
        if (n->stay == nullptr) {
            n->stay = new node;
            n->stay->id = ctr++;
            n->stay->path = n->path + "S";
        }
        next = n->stay;
    }
    next->moveUpCost += getMoveUpCost(x, i);

    add(x, i-1, next);
}

ll solve(node *x) {
    string path = x->path;
    ll ans = 0;

    ii y = make_pair(0, 0);
    for (int i = 0; i < 31; i++) {
        char c = i >= sz(path) ? 'S' : path[i];
        if (c == 'D') {
            y.f += (1 << (30-i));
        } else if (c == 'R') {
            y.s += (1 << (30-i));
        }
    }

    for (auto x : A) {
        ans += solveSimple(x, y);
    }

    return ans;
}

ll dp(node *x) {
    ll best = solve(x);

    if (x->down) {
        best = min(best, dp(x->down));
    }

    if (x->right) {
        best = min(best, dp(x->right));
    }

    if (x->stay) {
        best = min(best, dp(x->stay));
    }

    return best;
}

int main() {
    cin.tie(0)->sync_with_stdio(0);

    cin >> n;
    A.resize(n);
    F0R(i, n) cin >> A[i].f >> A[i].s;

    for (auto x : A) add(x, 30, &root);

    cout << dp(&root) << endl;

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...