zoukankan      html  css  js  c++  java
  • 【题解】HackerRank – Yet Another Minimax Problem

    题目

    https://www.hackerrank.com/challenges/yet-another-minimax-problem

    题意

    给出 n 个整数,求一个排列使得相邻两数的异或值的最大值最小,输出该值。

    题解

    • 如果有一位所有数都是 0 或 1,则异或之后这一位始终是 0。
    • 如果有一位既有 1 又有 0,我可以把 1 和 0 各自放在一起,但是会由一个交界处,交界处的异或值的该位为 1,其他位置是 0。
    • 问题就是找到所有数不完全相同的最高的那位,然后按那位是 0 或 1 分成两组,求两组分别取一个数是异或值最小。
    • 利用 Trie 求一个数与一堆数异或的最小值。

    AC代码

     #include <bits/stdc++.h> 

    #define FOR(i, x, y) for (remove_const<decltype(y)>::type i = (x), _##i = (y); i < _##i; ++i)
    #define FORD(i, x, y) for (remove_const<decltype(x)>::type i = (x), _##i = (y); i > _##i; --i)
    using namespace std;
    typedef long long LL;
    const int maxn = 3000 + 10;
    int n, a[maxn], b[maxn], la, lb, m;
    int trie[maxn * 20][2];
    int sz = 1;

    void (int n) {
    int u = 0;
    FORD(i, m - 1, -1) {
    bool b = (1 << i) & n;
    if (!trie[u][b]) trie[u][b] = sz++;
    u = trie[u][b];
    }
    }

    int query(int n) {
    int u = 0, ret = 0;
    FORD(i, m - 1, -1) {
    bool b = (1 << i) & n;
    if (!trie[u][b]) {
    ret += (1 << i);
    b ^= 1;
    }
    u = trie[u][b];
    }
    return ret;
    }

    int main() {
    cin >> n;
    m = 0;
    LL p = -1, q = 0;
    FOR(i, 0, n) {
    cin >> a[i];
    p &= a[i];
    q |= a[i];
    }
    if (!(p ^ q)) { puts("0"); return 0; }
    m = 31 - __builtin_clz(p ^ q);
    FOR(i, 0, n) {
    if (a[i] & (1 << m)) a[la++] = a[i];
    else b[lb++] = a[i];
    }
    FOR(i, 0, la) add(a[i]);
    LL ans = 1E10;
    FOR(i, 0, lb) ans = min(ans, (LL)query(b[i]));
    cout << ans + (1 << m) << endl;
    }
  • 相关阅读:
    丑数系列
    452. 用最少数量的箭引爆气球
    406. 根据身高重建队列
    763. 划分字母区间
    所有二叉树题目记录
    二叉树前中后序遍历非递归(迭代)解法
    二叉树的层序遍历题目汇总
    442. 数组中重复的数据&&448. 找到所有数组中消失的数字
    225. 用队列实现栈(Easy)
    使用ClosedXML读写excel
  • 原文地址:https://www.cnblogs.com/xxxsans/p/12603772.html
Copyright © 2011-2022 走看看