异或

leetcode1310. 子数组异或查询

十年热恋 提交于 2020-01-10 07:33:01
最近一直没参加周赛,今天遇到这道题,感觉有点意思,可以试着写下心路历程 题目: 有一个正整数数组 arr,现给你一个对应的查询数组 queries,其中 queries[i] = [Li, Ri]。 对于每个查询 i,请你计算从 Li 到 Ri 的 XOR 值(即 arr[Li] xor arr[Li+1] xor … xor arr[Ri])作为本次查询的结果。 并返回一个包含给定查询 queries 所有结果的数组。 示例 1: 输入:arr = [1,3,4,8], queries = [[0,1],[1,2],[0,3],[3,3]] 输出:[2,7,14,8] 解释: 数组中元素的二进制表示形式是: 1 = 0001 3 = 0011 4 = 0100 8 = 1000 查询的 XOR 值为: [0,1] = 1 xor 3 = 2 [1,2] = 3 xor 4 = 7 [0,3] = 1 xor 3 xor 4 xor 8 = 14 [3,3] = 8 示例 2: 输入:arr = [4,8,2,10], queries = [[2,3],[1,3],[0,0],[0,3]] 输出:[8,0,4,4] 提示: 1 <= arr.length <= 3 * 10^4 1 <= arr[i] <= 10^9 1 <= queries.length <= 3 * 10^4

深入理解按位异或运算符

让人想犯罪 __ 提交于 2020-01-10 04:01:05
深入理解按位异或运算符 参与运算的两个值,如果两个相应bit位相同,则结果为0,否则为1。 即:    0^0 = 0, 1^0 = 1, 0^1 = 1, 1^1 = 0 按位异或的3个特点: (1) 0^0=0,0^1=1 0异或任何数=任何数 (2) 1^0=1,1^1=0 1异或任何数-任何数取反 (3) 任何数异或自己=把自己置0 按位异或的几个常见用途: (1) 使某些特定的位翻转 例如对数10100001的第2位和第3位翻转,则可以将该数与00000110进行按位异或运算。       10100001^00000110 = 10100111 (2) 实现两个值的交换,而不必使用临时变量。 例如交换两个整数a=10100001,b=00000110的值,可通过下列语句实现:     a = a^b;   //a=10100111     b = b^a;   //b=10100001     a = a^b;   //a=00000110 (3) 在汇编语言中经常用于将变量置零: xor a,a (4) 快速判断两个值是否相等 举例1: 判断两个整数a,b是否相等,则可通过下列语句实现: return ((a ^ b) == 0) 举例2: Linux中最初的ipv6_addr_equal()函数的实现如下: static inline int ipv6_addr

位运算(&与,|或,^异或)

混江龙づ霸主 提交于 2020-01-10 00:24:51
整数在计算机中用二进制的位来表示,C语言提供一些运算符可以直接操作整数中的位,称为位运算,这些运算符的操作数都必须是整型的。 & 按位与, | 按位或 , ^ 按位异或 AND (位与&) OR ( 位或| ) XOR ( 位异或^ ) 1 & 1 = 1, 1 | 1 = 1, 1 ^ 1 = 0 1 & 0 = 0, 1 | 0 = 1, 1 ^ 0 = 1 0 & 1 = 0, 0 | 1 = 1, 0 ^ 1 = 1 0 & 0 = 0, 0 | 0 = 0, 0 ^ 0 = 0 运算规则: 1:按位与运算 按位与运算符"&"是双目运算符。 其功能是参与运算的两数各对应的二进位相与。只有对应的 两个二进位均为1时,结果位才为1 ,否则为0 。 2:按位或运算 按位或运算符“|”是双目运算符。 其功能是参与运算的两数各对应的二进位相或。只要对应的 两个二进位有一个为1时,结果位就为1 。 3:按位异或运算 按位异或运算符“^”是双目运算符。 其功能是参与运算的两数各对应的二进位相异或,当 两对应的二进位相异时,结果为1 。 来源: CSDN 作者: EVERZJS 链接: https://blog.csdn.net/weixin_44641254/article/details/103911988

集训Day12

北城余情 提交于 2020-01-09 07:08:42
快乐 快乐就完事了 今天把Trie树 / 可持久化Trie树搞了一下 Trie树可以维护区间最大异或和 具体就是区间异或和 -> 区间两个前缀异或和的异或 然后就变成了 "从n个数里找2个数,使他们异或起来最大" 怎么办呢 把串高位补0补成所有串一样长 然后从高到低建一颗$\sum$为2——只有'0'和'1'两个字符的Trie树 然后$O(n)$枚举第一个串 然后在Trie上跑一个贪心,从高到低,如果这一位是0就去找1,如果是1就去找0 这样就$O(nlogn)$完成了 “一个序列,找出一个区间,使他们的异或和最大,求这个最大的异或和” 如果是 “一个序列,多次询问,每次询问一个区间,找一个子区间使子区间异或和最大” 那就是在这个区间里建一棵Trie树,然后查 但每次建树是$O(n)$的,所以我们可以考虑像可持久化线段树一样建一个可持久化Trie树出来 可持久化Trie树满足性质,每次只会修改一条链,最多$logn$个点 于是我们可以在时间空间都是$O(nlog^2n)$的复杂度里完成这个操作 例题 bzoj3261 直接用可持久化Trie树模拟即可 bzoj5338 一棵树 1 x y 查询节点x的子树中与y异或结果的最大值 2 x y z 查询路径x到y上点与z异或结果最大值 对于1询问 对原树树剖一下 利用树剖编号建立可持久化Trie 即维护按编号顺序的前缀 对于询问2

Java的运算符

大城市里の小女人 提交于 2020-01-09 00:01:21
1.算数运算符   + 加  - 减  * 乘  / 除   % 取模(取余)  ++ 自增  -- 自减 整数相除只能得到整数。如果想得到小数,必须把数据变化为浮点类型的数据。   自增和自减运算,在单独使用,效果是一样的。   在参与其它运算时:    ++ 在前 当前数先 +1 ,在进行其它运算。    ++ 在后 先进行其它运算,当前数在 +1。    -- 在前 当前数先 -1 ,在进行其它运算。    -- 在后 先进行其它运算,当前数在 -1。   常量不可以是用 自增和自减运算。 2.赋值运算符   基本的赋值运算符:=   扩展的赋值运算符:+= , -= , *= , /= , %= 扩展的赋值运算符,隐含了一个强制类型转换 3.比较运算符   == , != , < , > , <= , >= , instanceof 不管操作简单还是复杂,结果肯定是boolean类型。   instanceof 判断是否是类的对象 Eg : "hello" instanceof String; true 4.逻辑运算符   & (AND 与)  | (OR 或)  ^(XOR 异或)    !(Not 非)   &&(短路与)  ||(短路或) 用于连接结果为布尔型的表达式。   ^(异或) 逻辑运算符 两边相同为 false 不同为true;   单 &

位运算——异或运算

只谈情不闲聊 提交于 2020-01-07 21:04:25
今天刷题时遇到一个题,本以为是暴力+大模拟,结果看完别人的AC代码后人都傻了,竟然是位运算。其中用到了异或 ^ 这种运算符。 先上原题连接 : 传送门 题目意思很好理解,有无限多个路灯,编号为1.2.3…刚开始时都是关着的,每次对一盏灯的操作都会改变它的状态(即开变成关,关变成开)。每次操作会给你一个实数a和一个整数b,一次操作是一次从1到b的k次循环,编号为a*k的实数部分的灯会改变状态。问,最后剩下的灯的编号为多少。 这是个很简单的模拟+暴力题,因为数据保证不超过2e6,所以我也用暴力的方法AC了 暴力AC代码: # include <stdio.h> # include <cstring> # include <iostream> # include <string> # include <cmath> # include <algorithm> # include <cstdlib> # include <queue> using namespace std ; int ans ; int tong [ 2000005 ] ; int main ( ) { int n ; double a , b ; cin >> n ; for ( int i = 0 ; i < n ; i ++ ) { cin >> a >> b ; for ( int j = 1 ; j <= b

LeetCode 136. Single Number

…衆ロ難τιáo~ 提交于 2020-01-06 20:51:13
136. Single Number(只出现一次的数字) 链接 https://leetcode-cn.com/problems/single-number 题目 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 说明: 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗? 示例 1: 输入: [2,2,1] 输出: 1 示例 2: 输入: [4,1,2,1,2] 输出: 4 思路 这题思路有点强的,我本来打算遍历加哈希来检测,之后发现了,这题可以用位运算(我从来没有想过这个问题)。 异或计算,如果二者相同则结果为0,不同的话结果为1,再加上异或自带的交换律,最后结果就是0异或单一数,就是要找的数字。 代码 public static int singleNumber(int[] nums) { int n = 0; for (int i = 0; i < nums.length; i++) { n = n ^ nums[i]; } return n; } 来源: https://www.cnblogs.com/blogxjc/p/12148140.html

集训Day12

不羁岁月 提交于 2020-01-06 04:02:16
快乐 快乐就完事了 今天把Trie树 / 可持久化Trie树搞了一下 Trie树可以维护区间最大异或和 具体就是区间异或和 -> 区间两个前缀异或和的异或 然后就变成了 "从n个数里找2个数,使他们异或起来最大" 怎么办呢 把串高位补0补成所有串一样长 然后从高到低建一颗$\sum$为2——只有'0'和'1'两个字符的Trie树 然后$O(n)$枚举第一个串 然后在Trie上跑一个贪心,从高到低,如果这一位是0就去找1,如果是1就去找0 这样就$O(nlogn)$完成了 “一个序列,找出一个区间,使他们的异或和最大,求这个最大的异或和” 如果是 “一个序列,多次询问,每次询问一个区间,找一个子区间使子区间异或和最大” 那就是在这个区间里建一棵Trie树,然后查 但每次建树是$O(n)$的,所以我们可以考虑像可持久化线段树一样建一个可持久化Trie树出来 可持久化Trie树满足性质,每次只会修改一条链,最多$logn$个点 于是我们可以在时间空间都是$O(nlog^2n)$的复杂度里完成这个操作 例题 bzoj3261 直接用可持久化Trie树模拟即可 bzoj5338 一棵树 1 x y 查询节点x的子树中与y异或结果的最大值 2 x y z 查询路径x到y上点与z异或结果最大值 对于1询问 对原树树剖一下 利用树剖编号建立可持久化Trie 即维护按编号顺序的前缀 对于询问2

LeetCode 136. Single Number

谁说胖子不能爱 提交于 2020-01-04 10:33:49
136. Single Number(只出现一次的数字) 链接 https://leetcode-cn.com/problems/single-number 题目 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 说明: 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗? 示例 1: 输入: [2,2,1] 输出: 1 示例 2: 输入: [4,1,2,1,2] 输出: 4 思路 这题思路有点强的,我本来打算遍历加哈希来检测,之后发现了,这题可以用位运算(我从来没有想过这个问题)。 异或计算,如果二者相同则结果为0,不同的话结果为1,再加上异或自带的交换律,最后结果就是0异或单一数,就是要找的数字。 代码 public static int singleNumber(int[] nums) { int n = 0; for (int i = 0; i < nums.length; i++) { n = n ^ nums[i]; } return n; } 来源: https://www.cnblogs.com/blogxjc/p/12148140.html

二进制枚举的一些思考和例题

淺唱寂寞╮ 提交于 2020-01-03 20:08:33
二进制枚举 固定模板 for (int i=0;i<(1<<n);i++) for(int j=0;j<n;j++) if(i&(1<<j)) 这样就把所有数遍历了一遍,用1<<去和i与就可以去选其中的某几个数 最后去应用这个方法解决一些问题 我觉得之所以用二进制思想去解决问题是因为二进制表示的一些巧妙的地方,这得慢慢 结合题目去悟 前提是得先学会二进制的一些基本运算法则 算数位运算: 1、与(&): 对于指定的两个数A=60(0011 1100) B=13(0000 1101) 执行一下操作 A&B=12(0000 1100) 就是对二进制每一位进行了一次与操作,同为1,结果为1,否则为0 其实说白了就是只要有0就是0; 2、或(|): 对于指定的两个数A=60(0011 1100) B=13(0000 1101) 执行一下操作 A|B=61(0011 1101) 就是对二进制每一位进行了一次或操作,同为0,结果为0,否则为1 说白了就是有1就为1; 关于与和或其实可以类比&& || 3、非 按位取反(~): 对于指定的一个数A=60(0011 1100) 执行以下操作 ~A=195(1100 0011) 就是对二进制每一位进行了一次取反操作,若二进制数位0,则变成1,否则变成0. 4、异或运算 a,b值不同为1(就是两个数一个1 一个0) 相同时为0; 在c/c++中异或用