首页 > 代码库 > bzoj3689

bzoj3689

trie+堆

跟超级钢琴是一个想法

我们先把每个数插进trie里,然后对于每个数查找异或第二小,因为第一小肯定是和自己。

然后就和超级钢琴一样,从堆里取出,插入第k+1小。trie是可以查找第k小的,只要维护一个size。

技术分享
#include<bits/stdc++.h>
using namespace std;
const int N = 100010, mod = 1000000007;
struct data {
    int v, p, rank;
    data(int v = 0, int p = 0, int rank = 0) : v(v), p(p), rank(rank) {}
    friend bool operator < (data A, data B)
    {
        return A.v > B.v;
    }
};
priority_queue<data> q;
int ans, n, m;
int a[N], bit[30];
struct trie {
    int cnt, root;
    int size[N * 26], child[N * 25][2];
    void insert(int &x, int val, int bit)
    {
        if(!x) x = ++cnt;
        ++size[x];
        if(bit < 0) return;
        int t = (val >> bit) & 1;
        insert(child[x][t], val, bit - 1); 
    }
    int query(int x, int val, int k, int bit)
    {
        if(bit < 0) return 0;
        int t = (val >> bit) & 1;
        if(size[child[x][t]] >= k) return query(child[x][t], val, k, bit - 1);
        else return query(child[x][t ^ 1], val, k - size[child[x][t]], bit - 1) + (1 << bit); 
    }
} t;
int main()
{
    scanf("%d%d", &n, &m);
    m *= 2;
    for(int i = 1; i <= n; ++i)
    {
        scanf("%d", &a[i]);
        t.insert(t.root, a[i], 30);
    }
    for(int i = 1; i <= n; ++i) q.push(data(t.query(t.root, a[i], 2, 30), i, 2));
    for(int i = 1; i <= m; ++i)
    {
        data x = q.top(); q.pop();
        if(i & 1) printf("%d ", x.v);
        q.push(data(t.query(t.root, a[x.p], x.rank + 1, 30), x.p, x.rank + 1));
    }
    return 0;
} 
View Code

 

bzoj3689