BZOJ 3689 异或之

来源:互联网 发布:linux删除arp 编辑:程序博客网 时间:2024/05/17 03:48

TRIE树+堆

如果只求最小的,我们可以建出TRIE树,对每一个数都跑一边求第二小(最小的是自己异或自己),这样一定包含了所有数的异或最小值,然后找最小的即可。

如果还需要求第二小,在排除第一小的情况下,我们把组成第一小的那个数在TRIE树上求一个第三小,这样同样依然包含了所有数的当前异或最小值,以此类推,堆维护即可。

注意a^b = b^a,也就是说一个值会出现两次,所以k应取k*2

#include<cstdio>#include<queue>#include<map>#define N 100005#define H 30using namespace std;int a[N], use[N];map<pair<int,int>,bool> vis;int nodecnt;struct node{    node *ch[2];    int siz;    node(){ch[0]=ch[1]=NULL;siz=0;}}s[N*50];struct TRIE{    node *root;    void init()    {        root = &s[++nodecnt];    }    void insert(int x)    {        node *p = root;        for(int i = H, pos = 1<<H; ~i; i--, pos>>=1)        {            if(!p->ch[0])p->ch[0]=&s[++nodecnt];            if(!p->ch[1])p->ch[1]=&s[++nodecnt];            int son = x&pos?1:0;            p=p->ch[son];            p->siz++;        }    }    int find(int x, int k)//第k小     {        node *p = root;        int ret = 0;        for(int i = H, pos = 1<<H; ~i; i--, pos>>=1)        {            int son = x&pos?1:0;            if(p->ch[son]->siz >= k)            {                ret<<=1;                p=p->ch[son];            }            else            {                ret<<=1;                ret|=1;                k-=p->ch[son]->siz;                p=p->ch[son^1];            }        }        return ret;    }}trie;struct number{    int x, v;    number(int a, int b):x(a),v(b){}    friend bool operator < (number a, number b)    {        return a.v>b.v;    } };int main(){    int n, k;    scanf("%d%d",&n,&k);    trie.init();    for(int i = 1; i <= n; i++)    {        scanf("%d",&a[i]);        trie.insert(a[i]);        use[i]=1;    }    priority_queue<number> q;    for(int i = 1; i <= n; i++)    {        ++use[i];        int num = trie.find(a[i],use[i]);        q.push(number(i,num));    }    for(int i = 1, ii = 2*k; i < ii; i++)    {        number x = q.top(); q.pop();        if(i&1)printf("%d ",x.v);        int pos = x.x, num;        if(use[pos]==n)continue;        use[pos]++;        num = trie.find(a[pos],use[pos]);        q.push(number(pos,num));    }    return 0;}
0 0