SPOJ SUBXOR

题意

给定一个由正整数构成的数组, 求 异或和小于k 的子序列的个数.

题解

假设答案区间为 [L, R], XOR[L, R] 等价于 XOR[1, L - 1] ^ XOR[1, R], 可以使用 01Trie 保存目前已有的 前缀异或和, 对于每一个新的前缀插入之前, 在 01Trie 中查询 与 新的前缀 异或值 小于 K 的 已有前缀和的个数.

对于每个TrieNode 的定义为

struct TrieNode {
TrieNode* next[2];
int cnt;
TrieNode() {
next[0] = next[1] = NULL;
// 保存当前前缀的个数
cnt = 0;
}
};

在进行查询时, 比较 新的前缀和 and k 的每一位

已有前缀和的第 i 位 indexPre( 新的前缀和的第 i 位) indexK( K 的第 i 位) 相应操作
0 0 0 递归求解左子树
1 0 1 统计左子树叶子节点个数, 递归求解右子树
1 1 0 递归求解右子树
0 1 1 统计右子树叶子节点个数, 递归求解左子树

对于 indexPre == 0, indexK == 0 的情况来说, 已有前缀和为 0 时满足条件, 因此需要递归求解左子树. 当已有前缀和为 1 时, indexK == 1, 大于要求的值, 所以不继续递归.

对于 indexPre == 0, indexK == 1 的情况来说, 已有前缀和为 1 时满足条件, 但 右子树 中可能有 值大于等于 K 的叶子节点, 因此需要递归求解右子树. 当已有前缀和为 0 时, indexK == 0, 所有左子树的叶子节点的值均小于 K, 因此统计左子树叶子节点的个数

AC代码

#include <cstdio>
#include <iostream>
using namespace std;
struct TrieNode {
TrieNode* next[2];
int cnt;
TrieNode() {
next[0] = next[1] = NULL;
cnt = 0;
}
};
void insertNum(TrieNode* root, unsigned num) {
TrieNode* p = root;
for(int i = 31; i >= 0; i--) {
int index = (num >> i) & 1;
if(!p->next[index])
p->next[index] = new TrieNode();
p = p->next[index];
p->cnt++;
}
}
int getCnt(TrieNode* root) {
return root ? root->cnt : 0;
}
int queryLessThanK(TrieNode* root, int pre, int k) {
TrieNode* p = root;
int ret = 0;
for(int i = 31; i >= 0; i--) {
if(p == NULL)
break;
int indexPre = (pre >> i) & 1; // prefiexbit
int indexK = (k >> i) & 1; // bit
if(indexPre == indexK) {
if(indexK)
ret += getCnt(p->next[1]);
p = p->next[0];
}
else if(indexPre != indexK) {
if(indexK)
ret += getCnt(p->next[0]);
p = p->next[1];
}
}
return ret;
}
int main() {
int nTest; scanf("%d", &nTest);
while(nTest--) {
int nNum, k;
scanf("%d %u", &nNum, &k);
TrieNode* root = new TrieNode();
// insertNum(root, 0) 保证了前缀异或和 pre 自身 可以小于 k
insertNum(root, 0);
unsigned pre = 0;
long long ans = 0;
while(nNum--) {
unsigned num; scanf("%u", &num);
pre = pre ^ num;
ans += queryLessThanK(root, pre, k);
insertNum(root, pre);
}
cout << ans << endl;
}
return 0;
}

SPOJ SUBXOR的更多相关文章

  1. BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 5217  Solved: 1233 ...

  2. SPOJ DQUERY D-query(主席树)

    题目 Source http://www.spoj.com/problems/DQUERY/en/ Description Given a sequence of n numbers a1, a2, ...

  3. SPOJ GSS3 Can you answer these queries III[线段树]

    SPOJ - GSS3 Can you answer these queries III Description You are given a sequence A of N (N <= 50 ...

  4. 【填坑向】spoj COT/bzoj2588 Count on a tree

    这题是学主席树的时候就想写的,,, 但是当时没写(懒) 现在来填坑 = =日常调半天lca(考虑以后背板) 主席树还是蛮好写的,但是代码出现重复,不太好,导致调试的时候心里没底(虽然事实证明主席树部分 ...

  5. SPOJ bsubstr

    题目大意:给你一个长度为n的字符串,求出所有不同长度的字符串出现的最大次数. n<=250000 如:abaaa 输出: 4 2 1 1 1 spoj上的时限卡的太严,必须使用O(N)的算法那才 ...

  6. 【SPOJ 7258】Lexicographical Substring Search

    http://www.spoj.com/problems/SUBLEX/ 好难啊. 建出后缀自动机,然后在后缀自动机的每个状态上记录通过这个状态能走到的不同子串的数量.该状态能走到的所有状态的f值的和 ...

  7. 【SPOJ 1812】Longest Common Substring II

    http://www.spoj.com/problems/LCS2/ 这道题想了好久. 做法是对第一个串建后缀自动机,然后用后面的串去匹配它,并在走过的状态上记录走到这个状态时的最长距离.每匹配完一个 ...

  8. 【SPOJ 8222】Substrings

    http://www.spoj.com/problems/NSUBSTR/ clj课件里的例题 用结构体+指针写完模板后发现要访问所有的节点,改成数组会更方便些..于是改成了数组... 这道题重点是求 ...

  9. SPOJ GSS2 Can you answer these queries II

    Time Limit: 1000MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Description Being a ...

随机推荐

  1. javascrapy 正则表达式验证 IP和MAC

    var psrc = $('input[name="psrc"]').val() var hwsrc = $('input[name="hwsrc"]').va ...

  2. js小数转分数-近似递归

    精度为小数两位,提高精度可把 toFixed(2)和100同时修改: function decimalsToFractional(decimals){ const formatDecimals = d ...

  3. Python入门-初始面向对象

    之前我们代码基本上都是面向过程的,今天我们就来初始一下python中一个重要的内容:面向对象 一.面向对象和面向过程(重点理解) 1.面向过程: 一切以事物的流程为核心. 核心是"过程&qu ...

  4. 【转载】javascript深入理解js闭包

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...

  5. Java链接 Oracle11g R2

    菜鸟学习Oracle数据库,使用Java代码链接数据库. 首先要配置Eclipse,在新建的工程中,Package Explorer->工程名->Build path->Add ex ...

  6. How to solve problems

    练习是为了帮助你成长 0.Don't panic! 1.What are the inputs? 2.What are the outputs? 3.Work through some example ...

  7. matlab练习程序(三角形外接圆)

    三角形两边的垂直平分线就能确定外接圆. 结果如下: matlab代码如下: clear all;close all;clc; p=rand(,); %(x,y) cen1=(p(,:)+p(,:))/ ...

  8. nlinfit非线性回归拟合

    % % 使用指定函数对下述两变量进行曲线拟合  % % y=a+k1*exp(m*t)+k2*exp(-m*t);  % % 离散点: t=[0,4,8,40],  % % y=[20.09,64.5 ...

  9. git revert .vs. git reset .vs. git rebase

    1. git rervert的工作方式是:将一个老的commit的改动完全找出来,并且在新的tip处运行反操作,最终清除老commit的改动: git revert的应用场景多在对public rep ...

  10. Azkaban调度器

    Azkaban介绍 Azkaban 是由 Linkedin 公司推出的一个批量工作流任务调度器,用于在一个工作流内以一个特定的顺序运行一组工作和流程.Azkaban 使用 job 配置文件建立任务之间 ...