SPOJ SUBXOR
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的更多相关文章
- 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 ...
- SPOJ DQUERY D-query(主席树)
题目 Source http://www.spoj.com/problems/DQUERY/en/ Description Given a sequence of n numbers a1, a2, ...
- 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 ...
- 【填坑向】spoj COT/bzoj2588 Count on a tree
这题是学主席树的时候就想写的,,, 但是当时没写(懒) 现在来填坑 = =日常调半天lca(考虑以后背板) 主席树还是蛮好写的,但是代码出现重复,不太好,导致调试的时候心里没底(虽然事实证明主席树部分 ...
- SPOJ bsubstr
题目大意:给你一个长度为n的字符串,求出所有不同长度的字符串出现的最大次数. n<=250000 如:abaaa 输出: 4 2 1 1 1 spoj上的时限卡的太严,必须使用O(N)的算法那才 ...
- 【SPOJ 7258】Lexicographical Substring Search
http://www.spoj.com/problems/SUBLEX/ 好难啊. 建出后缀自动机,然后在后缀自动机的每个状态上记录通过这个状态能走到的不同子串的数量.该状态能走到的所有状态的f值的和 ...
- 【SPOJ 1812】Longest Common Substring II
http://www.spoj.com/problems/LCS2/ 这道题想了好久. 做法是对第一个串建后缀自动机,然后用后面的串去匹配它,并在走过的状态上记录走到这个状态时的最长距离.每匹配完一个 ...
- 【SPOJ 8222】Substrings
http://www.spoj.com/problems/NSUBSTR/ clj课件里的例题 用结构体+指针写完模板后发现要访问所有的节点,改成数组会更方便些..于是改成了数组... 这道题重点是求 ...
- SPOJ GSS2 Can you answer these queries II
Time Limit: 1000MS Memory Limit: 1572864KB 64bit IO Format: %lld & %llu Description Being a ...
随机推荐
- log4j2分层输出日志
在java mvc框架开发过程中,我们经常的将代码分为类似controller(控制层).service(业务层).rpc(远程接口调用层).dao(数据层)等层级,如果将所有层级的日志全部都打到一个 ...
- struts2 国际化语言转换
学习struts2,了解了使用struts2的配置文件可以走向国际化,实现页面的语言转换.我已中文和英文为例,简单的实现登录页面的国际化 废话不多说,上代码 一,login.jsp页面 使用s标签&l ...
- mysql 笔记3
--建库create database dsdb DEFAULT CHARACTER set utf8 collate utf8_general_ci;/*删除数据库drop DATABASE 数据库 ...
- css3之弹性盒模型初探(一)
什么是弹性盒模型? 弹性盒模型是指在父级改变大小的时候内部的自己元素也会相应的改变大小,即子集会按照父级的大小按比例自适应大小. 弹性盒模型的提出可以解决一些响应式布局的需求 如何使用弹性盒模型? ...
- ECMAScript5提供了9个新数组方法:遍历、映射、过滤、检测、简化、和搜索数组
大多数方法的第一个参数接收一个函数,并且对数组的每个元素调用一次该函数.如果是稀疏数组,对不存在的元素不调用传递的函数.在大多数情况下,调用提供的函数使用三个参数:数组元素,元素的索引,数组本身,通常 ...
- 移动web中的幻灯片切换效果
百度或者谷歌下类似的插件有很多,原理都差不多,关键适合自己的项目,如果移动端要引入jquery这么大的插件,只能呵呵了.... 下面是工作中针对webkit内核的浏览器写的,html很简单: < ...
- 基于svg.js实现对图形的拖拽、选择和编辑操作
本文主要记录如何使用 svg.js 实现对图形的拖拽,选择,图像渲染及各类形状的绘制操作. 1.关于SVG SVG 是可缩放的矢量图形,使用XML格式定义图像,可以生成对应的DOM节点,便于对单个图形 ...
- Spark企业级应用开发和调优
1.Spark企业级应用开发和调优 Spark项目编程优化历程记录,主要介绍了Spark企业级别的开发过程中面临的问题和调优方法.包含合理分配分片,避免计算中间结果(大数据量)的collect,合理使 ...
- vue中全局引入bootstrap.css
1.首先在官网上下载bootstrap的压缩包(必须是官网上下载的) 将压缩包解压后引入在项目文件夹下面.如下图所示: 2.在main.js中引入 import './assets/bootstrap ...
- babel的使用以及安装配置
简介 babel是一个广泛使用的转码器,可以将ES6代码转化为ES5代码,从而在现有环境执行,这意味着,你可以现在就用ES6编写程序,而不用担心现有环境是否支持. 安装及配置 npm install ...