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的主要内容,如果未能解决你的问题,请参考以下文章

DTOJ2704:数字互换

DTOJ2700:hello world

DTOJ #3194. 去月球

DTOJ2703:两个数的余数和商

dtoj3433. 优美的字符串(str)

DTOJ1001:长方形周长和面积