BZOJ3689 异或之

来源:互联网 发布:unity3d raycasthit2d 编辑:程序博客网 时间:2024/04/28 14:31
题目大意:给定n个非负整数A[1], A[2], ……, A[n]。
对于每对(i, j)满足1 <= i < j <= n,得到一个新的数A[i] xor A[j],这样共有n*(n-1)/2个新的数。求这些数(不包含A[i])中前k小的数。

注:xor对应于pascal中的“xor”,C++中的“^”。


思路:同NOI2010超级钢琴。http://blog.csdn.net/wyfcyx_forever/article/details/40400327

我们只需一开始在全局堆中放进去每个数和他之后的数异或的最小值,然后在每次出堆的的时候再放进堆中第k+1小值即可。这样重复k次。

那么问题就变成了快速求某段区间给定一个数进行xor的第k小值,我们利用可持久化trie维护size直接在树上二分即可。

时间复杂度依旧O(klogn).


Code:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std; #define N 100010int w[N]; int ch[N<<5][2], size[N<<5], ind;int root[N];int Newadd(int Last, int bit, int x) {    int q = ++ind;    ch[q][0] = ch[Last][0], ch[q][1] = ch[Last][1];    size[q] = size[Last] + 1;         if (bit < 0)        return q;         if ((x >> bit) & 1)        ch[q][1] = Newadd(ch[Last][1], bit - 1, x);    else        ch[q][0] = Newadd(ch[Last][0], bit - 1, x);    return q;}int getkth(int Left, int Right, int x, int k) {    int res = 0, better;    bool d;    for(int dep = 30; dep >= 0; --dep) {        d = (x >> dep) & 1;        better = size[ch[Right][d]] - size[ch[Left][d]];        if (better >= k)            Left = ch[Left][d], Right = ch[Right][d];        else            Left = ch[Left][d ^ 1], Right = ch[Right][d ^ 1], res += (1<<dep), k -= better;    }         return res;} struct st {    int end, kth, val;    st(int _end = 0, int _kth = 0, int _val = 0):end(_end),kth(_kth),val(_val){}    bool operator < (const st &B) const {        return val < B.val;    }}; #define K 250010struct Heap {    st a[K];    int top;    Heap():top(0){}    inline void up(int x) {        for(; x != 1; x >>= 1)            if (a[x]<a[x>>1])                swap(a[x],a[x>>1]);            else                break;    }    inline void down(int x) {        int son;        for(; (x<<1)<=top; ) {            son=(((x<<1)==top)||(a[x<<1]<a[(x<<1)|1]))?(x<<1):((x<<1)|1);            if (a[son]<a[x])                swap(a[son],a[x]),x=son;            else                break;        }    }    inline void push(const st &x) {        a[++top] = x;        up(top);    }    st Min() {        return a[1];    }    inline void pop() {        a[1] = a[top--];        down(1);    }}H; int main() {    int n, k;    scanf("%d%d", &n, &k);         register int i, j;    for(i = 1; i <= n; ++i) {        scanf("%d", &w[i]);        root[i] = Newadd(root[i - 1], 30, w[i]);    }         for(i = 2; i <= n; ++i)        H.push(st(i, 1, getkth(root[0], root[i - 1], w[i], 1)));         for(i = 1; i <= k; ++i) {        st tmp = H.Min();        H.pop();        if (i != 1)            putchar(' ');        printf("%d", tmp.val);        if (tmp.kth != tmp.end - 1)            H.push(st(tmp.end, tmp.kth + 1, getkth(root[0], root[tmp.end - 1], w[tmp.end], tmp.kth + 1)));    }         return 0;}


0 0
原创粉丝点击