【题目描述】
给定一个长度为 $n$ 的序列 $a_i$,求第 $k$ 大的 $a_i ^ land a_j (i eq j)$ 值。
【输入格式】
第一行两个正整数 $n,k$。
第二行 $n$ 个正整数,第 $i$ 个为 $a_i$。
【输出格式】
一行一个数表示答案。
【样例】
样例输入
4 4
2 3 4 6
样例输出
6
【数据范围与提示】
除 $k$外所有数不超过 $5 imes 10^4,k leq n imes (n-1)$。
【题解】
看到两个数的异或值,不难想到 $Trie$。
由于第 $k$ 大并不方便逐位贪心,考虑二分。
二分 $check$ 时暴力从根节点开始跑,直接 $dfs$ 整颗 $Trie$ 即可。
效率 $O(2^{16} imes 16)$。
【代码】
#include<bits/stdc++.h> inline long long read ( void ) { long long x=0;char ch;bool f=true; while ( !isdigit(ch=getchar()) ) if ( ch=='-' ) f=false; for ( x=ch^48;isdigit(ch=getchar()); ) x=(x<<1)+(x<<3)+(ch^48); return f ? x : -x ; } const int maxn=50000+10; struct Trie { int ch[maxn*100][17],val[maxn*100],tot; inline void insert ( int x ) { int u=1; for ( int i=15;~i;i-- ) { int k=(x>>i)&1; if ( !ch[u][k] ) ch[u][k]=++tot; u=ch[u][k];val[u]++; } } inline long long solve ( int u,int v,int x,int dep ) { if ( !(~dep) ) return 1LL*val[u]*val[v]; if ( !u or !v ) return 0; if ( (x>>dep)&1 ) { if ( u==v ) return solve(ch[u][0],ch[v][1],x,dep-1); else return solve(ch[u][0],ch[v][1],x,dep-1)+solve(ch[u][1],ch[v][0],x,dep-1); } else return val[ch[u][0]]*val[ch[v][1]]+(u!=v)*val[ch[u][1]]*val[ch[v][0]]+solve(ch[u][0],ch[v][0],x,dep-1)+solve(ch[u][1],ch[v][1],x,dep-1); } }T; signed main() { int n=read();long long k=read();T.tot++; while ( n-- ) T.insert(read()); int L=0,R=(1<<16)-1; while ( L<R ) { int mid=(L+R+1)>>1; if ( 2LL*T.solve(1,1,mid,15)>=k ) L=mid; else R=mid-1; } return !printf("%d ",L); }