DTOJ #3315. fullcombo
Posted rensheyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DTOJ #3315. fullcombo相关的知识,希望对你有一定的参考价值。
【题目描述】
给定一个长度为 $n$ 的序列 $a_i$,求第 $k$ 大的 $a_i ^ \land a_j (i \neq j)$ 值。
【输入格式】
第一行两个正整数 $n,k$。
第二行 $n$ 个正整数,第 $i$ 个为 $a_i$。
【输出格式】
一行一个数表示答案。
【样例】
样例输入
4 4
2 3 4 6
样例输出
6
【数据范围与提示】
除 $k$外所有数不超过 $5\times 10^4,k \leq n\times (n-1)$。
【题解】
看到两个数的异或值,不难想到 $Trie$。
由于第 $k$ 大并不方便逐位贪心,考虑二分。
二分 $check$ 时暴力从根节点开始跑,直接 $dfs$ 整颗 $Trie$ 即可。
效率 $O(2^16\times 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\n",L);
以上是关于DTOJ #3315. fullcombo的主要内容,如果未能解决你的问题,请参考以下文章