首页 > 其他分享 >统计异或值在范围内的数对有多少(01字典树)

统计异或值在范围内的数对有多少(01字典树)

时间:2023-01-07 13:45:17浏览次数:64  
标签:cnt 01 nums int high trie 异或 字典

1803. 统计异或值在范围内的数对有多少 - 力扣(Leetcode)


题意:

 

 

 


思路:

  • 很经典的方法,01字典树,同时在树上多维护一个数据,有多少个节点经过当前节点,记为cnt
  • 我们可以写出一个query(x,tar)函数,x时num数组中的数,答案就是query(x,high)- query(x,low-1)
  • 构造一棵空树,然后在每个节点插入,按照 x 向下查找位置时,记录经过的点在之前有多少个节点经过(因为题目有一个i < j 的条件),然后讨论从高位往低位
    1. tar 当前第 i 位二进制为 1 时,说明异或对结果的第 i 位可以为 0 或 1。往异或结果为 0 的子节点走,之后所有的必然都比 tar 小,可以直接加上这个子节点的cnt;往异或结果为 1 的子节点走,之后需再判断
    2. tar 当前第 i 位二进制为 0 时,说明异或对结果的第 i 位只能为 0。只能往对应的子节点走
    3. 在上面的走法,如果无法走,就停止,返回已经算出来的数量
  • 像这样计算一个,插入一个就能得到答案了

const int N = 20005;
int trie[N * 15][2], cnt[N * 15], idx;
class Solution { 
public:
    int countPairs(vector<int>& nums, int low, int high) {
        return get(nums, high) - get(nums, low - 1);
    }
    int get(vector<int>& nums, int high) {
        idx = 0;
        memset(trie, 0, sizeof(trie));
        memset(cnt, 0, sizeof(cnt));
        int ans = 0;
        for (int i = 0; i < nums.size(); i++) {
            ans += query(nums[i], high);
            add(nums[i]); 
        }
        return ans;
    }
    void add(int x) {
        int p = 0;
        for (int i = 14; i >= 0; i--) {
            int u = (x >> i)  & 1;
            if (trie[p][u] == 0) trie[p][u] = ++idx;
            p = trie[p][u]; //移动到下一个结点 
            cnt[p]++; // 个数增加,cnt[x]代表x结点出现的次数
        }
    }
    int query(int x, int high) {
        int sum = 0, p = 0;
        for  (int i = 14; i >= 0; i--) {
            int u = (x >> i) & 1;
            if (((high >> i) & 1) == 1) { //high当前i位为1, 那么x与以前数当前i位的异或可以位1或者0
                sum += cnt[trie[p][u]];//加上与x异或后当前i位为0的数量
                if (trie[p][u ^ 1] == 0) return sum; //没有结点可以继续走下去,直接返回
                p = trie[p][u ^ 1]; //继续往异或的结点走下去
            } else { //high当前i位为0, x与以前数异或的第i为必须为0
                if (trie[p][u] == 0) return sum; //没有结点走下去
                p = trie[p][u]; //寻找与x的第i位相同的进制,异或结果为0
            }
        }
        sum += cnt[p]; //加上走到最后的结点数
        return sum;
    }
};

 

标签:cnt,01,nums,int,high,trie,异或,字典
From: https://www.cnblogs.com/cfddfc/p/17032530.html

相关文章

  • C语言程序设计课程设计[2023-01-07]
    C语言程序设计课程设计[2023-01-07]C语言程序设计课程设计要求一、课程设计目的1.进一步掌握和利用C语言进行程设计的能力;2.进一步理解和运用结构化程设计的思想和......
  • 001.Stream介绍
    1.介绍  2.Stream示例  3.常用方法 ......
  • Oracle数据恢复故障处理之启动报错:ORA-03113: end-of-file on communication channel
    lsnrctl启动实例startup报错ORA-03113:end-of-fileoncommunicationchannel $su-oracleStep1:Youneedtolookatthealertlog.Itisn'tin/var/logas......
  • 【230107-1】给定等式:2x平方+3x+5m=0,若其一根大于1,求m的取值范围?
    Givenanequation:2x*x+3x+5m=0.Ifonerootoftheequationislargerthan1,thenthevaluerangeofmis()A.m<-1B.|m|<1C.0<m<1D.m<=-1释义:给定等式:2x*x+3x+5m=0,若其......
  • [RMQ记录] P2048 [NOI2010] 超级钢琴
    题目如果枚举所有的情况肯定是不行的。不过可以发现一些对答案完全没有影响的答案也被枚举,十分浪费时间,所以下面介绍一种很好的思路。首先,考虑优化暴力(暴力指用堆维护每......
  • Alluer01-介绍
    什么是allureallure是一款轻量级并且非常灵活的开源测试报告框架支持绝大多数测试框架,例如TestNG、Pytest、JUint等简单易用,易于集成在python中使用allure,需要安装allure-p......
  • 新概念第一册101~110单元学习笔记
    ChapterOnehundredandone:acardfromjimmyDialogue间接引语:1、引号去掉2、转换人称3、添加引导词tha直接引用:实际讲得话放在引号中间‘ihavejustarrivedinScotla......
  • 2023 0107 关于英语思维之翻译
    在英语学习过程中,很关键的一个因素,就是形成英语思维.你能够熟练的使用合适的单词,短语,加上正确的时态,以及句子结构,构成一个正确的句子.要想构成一个或者说出来一个......
  • 2023年01月编程语言流行度排名
    点击查看最新编程语言流行度排名(每月更新)2023年01月编程语言流行度排名编程语言流行度排名是通过分析在谷歌上搜索语言教程的频率而创建的一门语言教程被搜索的次数越多......
  • C/C++学生信息管理系统[2023-01-06]
    C/C++学生信息管理系统[2023-01-06]题目6学生信息管理系统(任选)本系统要求设计一个学生信息管理系统,能够进行学生信息的录入、查找,要求考虑查找效率。本题目要求采用......