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. Java基础(十)数据结构

    一.数据结构 1.数据结构的定义 数据结构是计算机存储,组织数据的方式.数据结构是指相互之间存在一种或多种特定关系的数据元素的集合.通常情况下,精心选择的数据结构可以带来更高的运行或存储效率.数据结构 ...

  2. 建一个springboot项目

    1.打开 https://start.spring.io/ 新建一个maven的demo,这里选择的是1.5.18的版本 2.将自动生成的demo导入eclipse,直接选中File里的import, ...

  3. Oracle自定义函数&加密

    在sql中频繁使用的功能(逻辑.加密等)可以写成自定义函数进行封装,之后再调用即可. CREATE OR REPLACE FUNCTION "函数名" (参数名 参数类型 参数数据 ...

  4. 如何检测页面是否有重复的id属性值

    <!DOCTYPE html> <html> <head> <meta charset=" utf-8"> <meta nam ...

  5. JavaScript This -笔记

    参考文章:blog.crimx.com/2016/05/12/understanding-this/ 在es6箭头函数之前this是执行时候确定的,而非定义时候确定.函数都是被调用的,调用时找前面调用 ...

  6. HTML5 : 文件上传下载

    网站建设中,文件上传与下载在所难免,HTML5中提供的API在前端有着丰富的应用,完美的解决了各个浏览器的兼容性问题,所以赶紧get吧! FileList 对象和 file 对象 HTML 中的 in ...

  7. js Array数组对象常见方法总结

    Array对象一般用来存储数据. 其常用的方法包括: 1.concat()方法 concat() 方法用于合并两个或多个数组.它不会更改现有数组,而是返回一个新数组. 例如: var arr1=[1, ...

  8. CentOS 7运维管理笔记(1)----设置默认启动模式为GUI模式或命令行模式

    昨天在虚拟机中安装CentOS 7时选择了GNOME模式安装,开机默认进入GUI模式.网上搜找修改为默认命令行模式的方法,看到说修改 /etc/inittab文件,在最低下一行添加 但是 使用 cat ...

  9. GreenDao 初体验

    GreenDao 使用 环境搭建(android studio) project的build.gradle buildscript { repositories { google() jcenter( ...

  10. 斐波那契数列(C++ 和 Python 实现)

    (说明:本博客中的题目.题目详细说明及参考代码均摘自 “何海涛<剑指Offer:名企面试官精讲典型编程题>2012年”) 题目 1. 写一个函数,输入 n, 求斐波那契(Fibonacci ...