BZOJ_3689_异或之_可持久化Trie+堆

BZOJ_3689_异或之_可持久化Trie+堆

Description

给定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++中的“^”。

Input

第一行2个正整数 n,k,如题所述。
以下n行,每行一个非负整数表示A[i]。

Output

 共一行k个数,表示前k小的数。

Sample Input

4 5
1
1
3
4

Sample Output

0 2 2 5 5


 

类似超级钢琴那道题,只不过这道题需要求一个数和区间内某数异或的最小值。

于是我们对前缀建立可持久化Trie,直接Trie树上贪心即可。

 

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <ext/pb_ds/priority_queue.hpp>
using namespace std;
using namespace __gnu_pbds;
#define N 100050
inline char nc() {
    static char buf[100000],*p1,*p2;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd() {
    register int x=0; register char s=nc();
    while(s<'0'||s>'9') s=nc();
    while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+s-'0',s=nc();
    return x;
}
struct A {
    int x,p,l,r,v;
    A() {}
    A(int x_,int p_,int l_,int r_,int v_) :
        x(x_),p(p_),l(l_),r(r_),v(v_) {}
};
int a[N],n,K,end[N*35];
inline bool operator < (const A &x,const A &y) {
    return x.v>y.v;
}
__gnu_pbds::priority_queue<A>q;
int root[N],ch[N*35][2],siz[N*35],cnt=1;
void insert(int k) {
    int i;
    root[k]=++cnt;
    int p=root[k],q=root[k-1];
    siz[p]=siz[q]+1;
    for(i=31;i>=1;i--) {
        int t=((a[k]>>(i-1))&1);
        ch[p][!t]=ch[q][!t];
        ch[p][t]=++cnt;
        p=ch[p][t];
        q=ch[q][t];
        siz[p]=siz[q]+1;
    }
    end[p]=k;
}
int query(int l,int r,int x) {
    int p=root[l-1],q=root[r],i,pos;
    for(i=31;i>=1;i--) {
        int t=((x>>(i-1))&1);
        if(siz[ch[q][t]]-siz[ch[p][t]]) {
            p=ch[p][t]; q=ch[q][t];
        }else {
            p=ch[p][!t]; q=ch[q][!t];
        }
    }
    return end[q];
}
void solve() {
    int i;
    for(i=1;i<n;i++) {
        int t=query(i+1,n,a[i]);
        q.push(A(i,t,i+1,n,a[i]^a[t]));
    }
    for(i=1;i<=K;i++) {
        A t=q.top(); q.pop();
        //printf("%d %d\n",t.x,t.p);
        printf("%d ",a[t.x]^a[t.p]);
        int d;
        if(t.p>t.l) d=query(t.l,t.p-1,a[t.x]),q.push(A(t.x,d,t.l,t.p-1,a[d]^a[t.x]));
        if(t.p<t.r) d=query(t.p+1,t.r,a[t.x]),q.push(A(t.x,d,t.p+1,t.r,a[d]^a[t.x]));
    }
}
int main() {
    n=rd(); K=rd();
    int i;
    for(i=1;i<=n;i++) {
        a[i]=rd();
        insert(i);
    }
    solve();
}

 

posted @ 2018-05-11 08:08  fcwww  阅读(176)  评论(0编辑  收藏  举报