D. Binary Spiders (thinking + dictionary tree)

Posted by titel on Thu, 13 Jan 2022 14:10:09 +0100

D. Binary Spiders

[Link](Problem - D - Codeforces)

meaning of the title

Here you are n n n numbers and one k k k. How many numbers can you choose at most and meet the XOR between any two ≥ k \ge k ≥k.

thinking

Consider how to use some properties to calculate the scheme, because it involves ⊕ \oplus ⊕ operation, we convert it into binary.

hypothesis k k Binary highest bit of k 1 1 1 is the second m m m bit

For any two numbers a , b a,b a. B if a , b a,b a. B binary m + 1 ∼ 29 m+1\sim29 If m+1 ∼ 29 is different, there must be a ⊕ b ≥ k ( from different or nature quality a ⊕ b two enter system of most high by one set than m high ) a\oplus b \ Ge K (by the XOR property, the highest binary value of a\oplus b must be higher than m) A ⊕ b ≥ K (due to the XOR property, the highest binary of a ⊕ b is higher than m), so we can choose any prefix with different prefixes.

Then prove that for the same prefix (binary bit) m + 1 ∼ 29 m+1\sim29 We can choose at most two numbers of m+1 ∼ 29 (the same).

hypothesis a , b , c a,b,c a. The prefixes B and C are the same and a ⊕ b ≥ k And a ⊕ c ≥ k a\oplus b\ge k and a\oplus c\ge k A ⊕ b ≥ k and a ⊕ c ≥ k

Then there are a and B two enter system of The first Binary second The m-th bit of binary must be a 0, a 1,a,c two enter system of The first Binary second The m-th bit of binary must be a 0 and a 1

be b , c b,c b. Binary bit of C m m The m bits are the same and the prefix is the same, so b ⊕ c < k b\oplus c<k b⊕c<k

Therefore, according to the drawer principle, two with the same prefix can be selected at most.

From the above properties, we group all numbers according to prefixes. For each prefix, we see whether there is a number and other XOR in the current group ≥ k \ge k ≥ k, contribution is 2 2 2. No contribution is 1 1 1.

Find the exclusive or maximum value of the previous number and current number in the same group. You can use the dictionary tree to maintain the complexity of l o g n logn logn, enumeration n n n. The total complexity is O ( n l o g n ) O(nlogn) O(nlogn).

Grouping can be used m a p map map, and then iterate through it with an iterator.

Special judgment k k k is 0 0 0 because k = = 0 k==0 If k==0, you should select all, but in the case of greed just now, only two will be selected in the same group.

Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <set>
#include <queue>
#include <vector>
#include <map>
#include <bitset>
#include <unordered_map>
#include <cmath> 
#include <stack>
#include <iomanip>
#include <deque> 
#include <sstream>
#define x first
#define y second
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long double ld;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef unsigned long long ULL;
const int N = 3e5 + 10, M = 2 * N, INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-8, pi = acos(-1), inf = 1e20;
#define tpyeinput int
inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}
inline void read(tpyeinput &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();}
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int h[N], e[M], ne[M], w[M], idx;
void add(int a, int b, int v = 0) {
    e[idx] = b, w[idx] = v, ne[idx] = h[a], h[a] = idx ++;
}
int n, m, k;
int a[N];
int tr[N * 30][2];
map<int, int> id;
map<int, vector<int>> mp;
vector<int> res;
int bits(int x) {
    int res = 0;
    while (x) {
        x >>= 1;
        res ++;
    }
    return res;
}
void insert(int x) {
    int p = 0;
    for (int i = 30; i >= 0; i -- ) {
        int u = x >> i & 1;
        if (!tr[p][u]) tr[p][u] = ++ idx;
        p = tr[p][u];
    }
}
int query(int x) {
    int p = 0, res = 0;
    for (int i = 30; i >= 0; i -- ) {
        int u = x >> i & 1;
        if (!tr[p][!u]) {
            p = tr[p][u];
            res = res * 2 + u;
        }
        else {
            p = tr[p][!u];
            res = res * 2 + !u;
        }
    }
    return res;
}
int main() {
    ios::sync_with_stdio(false), cin.tie(0);
    cin >> n >> k;
    m = bits(k);
    for (int i = 1; i <= n; i ++ ) {
        cin >> a[i];
        int x = (a[i] >> m);
        mp[x].push_back(a[i]);
        id[a[i]] = i;
    }
    if (!k) {
        cout << n << endl;
        for (int i = 1; i <= n; i ++ ) 
            cout << i << ' ';
        cout << endl;
        return 0;
    }
    map<int, vector<int>> ::iterator iter;
    for (iter = mp.begin(); iter != mp.end(); iter ++ ) {
        memset(tr, 0, sizeof (int)*2 * (idx + 1)), idx = 0;
        vector<int> ve = iter->second;
        int one = -1; 
        bool ok = false;
        for (auto x : ve) {
            insert(x);
            int t = query(x);
            if ((t ^ x) >= k) {
                ok = true;
                res.push_back(id[t]);
                res.push_back(id[x]);
                break;
            }
            one = id[x];
        }
        if (one && !ok) res.push_back(one);
    }
    if (res.size() <= 1) cout << -1 << endl;
    else {
        cout << res.size() << endl;
        for (auto x : res)  cout << x << ' ';
        cout << endl;            
    }
    return 0;
}

Topics: Algorithm Dynamic Programming greedy algorithm