• #3315. fullcombo


    题目描述

    SmallBell最近沉迷Lovelive,苦于[Beat In Angel]的fc。他在研究用什么队伍的时候,顺便把队伍的Cool属性也记录了下来,于是他得到 $n$ 个数。

    旁边的WerKeyTom_FTD正苦于如何卡常数。他突然对SmallBell提了个问题:选择两个数 $i,j$ $(i eq j)$ ,把第 $i,j$ 个数异或起来,求第 $k$ 大的异或值是多少。注意: $(i,j)$ 和 $(j,i)$ 是不同方案。

    SmallBell:好水啊,一下就切了!然后把问题交给了你。

    数据范围

    除 $k$ 外所有数为不大于 $5 imes 10^4$ 的正整数, $1 le k le n imes (n-1)$

    题解

    建立 $trie$ 树,考虑二分答案,然后每个数在 $trie$ 树上找出异或值 $≥mid$ 的个数总和,然后和 $k$ 判断即可,效率: $O(nlog^2n)$

    代码

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int N=5e4+5;
    int n,a[N],l,r=(1<<16)-1,d,t=1;
    LL k;
    struct O{
        int ch[2],sz;
    }tr[N*50];
    void ins(int x){
        int p=1;
        for (int v,i=15;~i;i--){
            v=(x>>i)&1;
            if (!tr[p].ch[v])
                tr[p].ch[v]=++t;
            p=tr[p].ch[v];tr[p].sz++;
        }
    }
    int get(int x){
        int p=1,sum=0;
        for (int v,i=15;~i;i--){
            v=(x>>i)&1;
            if (d&(1<<i))
                p=tr[p].ch[v^1];
            else 
                sum+=tr[tr[p].ch[v^1]].sz,
                p=tr[p].ch[v];
        }
        return sum+tr[p].sz;
    }
    bool J(){
        LL sum=0;
        for (int i=1;i<=n;i++)
            sum+=1ll*get(a[i]);
        return (sum>=k);
    }
    int main(){
        scanf("%d%lld",&n,&k);
        for (int i=1;i<=n;i++)
            scanf("%d",&a[i]),ins(a[i]);
        while(l<r){
            d=(l+r+1)>>1;
            if (J()) l=d;
            else r=d-1;
        }
        return printf("%d
    ",l),0;
    }
  • 相关阅读:
    adb shell dumpsys的使用
    appium框架之bootstrap
    adb forward交互流程
    adb shell中的am pm命令
    appium日志示例解读
    移动自动化相关名词解释
    appium架构分析
    solr单机环境配置并包含外部单机zookeeper
    Linux下常用的硬件信息查看命令
    Zookeeper服务常用的操作命令
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/11327028.html
Copyright © 2020-2023  润新知