题目链接:http://codeforces.com/problemset/problem/665/E

(http://www.fjutacm.com/Problem.jsp?pid=2255)

题意:找出有多少个连续的区间[l,r](1  ≤  l  ≤  r  ≤  n),该区间中所有的数的异或值大于等于k;

思路:首先,如果是单看题目的话,会发现暴力的话复杂度是O(n^3),但是我们先预处理异或前缀和,然后你会发现[l,r]区间的异或和等于s[l-1]^s[r],这样就可以O(n^2)的求得答案了,但是因为n是1e6,也就是说暴力绝对超时,因为时间才开了3s(虽然说cf里一秒时限,1e10复杂度也可以莽一莽,但是这个是1e12啊!!)。然后,我们会想,因为是异或,而且是要比较,于是乎我们就想到了字典树(不要问为什么,我就是这样想到的)。然后我们可以开始一波分析:

{

假设:全是5位二进制(默认补全到5位)

前提:S[i]是前i个数的异或和,  K为题目里的K,  A是S[i]^A=K 即S[i]^K=A

S[i] = 5

K  = 24

从高位到低位存入字典树时(默认已经存入,现在在find操作):

{

S[i]:00101

K : 11000

第五位时:k=1,则说明这一位必须往S[i]第五位的异或值方向走,因为我们现在是在查A在字典树上的路径,至于为什么只跑这个数就可以求答案,我们慢慢来。

     第四位同理;

       第三位时:(#敲黑板划重点)这个时候K的第三位为0,按照我说的来看,我们找A在树上的路径,那么此时我们要跑的下一步是S[i]的第三位和K第三位的异或值也就是A的第三位,那么如果我下一步不往这个方向走呢(此时A的第三位等于S[i]的第三位)?我往S[i]的第三位异或1的方向跑(反向),那么那个方向延伸的树枝上的所有数字就都是大于K的(这里不做解释),也就是我们虽然不需要跑那里,但是我们要加上经过那个延伸出去的树枝包含的数字个数;

     第二位、第一位同第三位的代码;

    在跑完所有的情况的时候,我们就求出了所有的A,A满足S[i]^A>k,没错,还少,还少一个等于的情况,此时,我们只需要判断我们是否跑完了5位,如果跑完了5位,就加上使用过当前节点的数的个数就得到了答案。

}

换一种说法其实就是在字典树上跑A这个数,如果跑到A这个数的某一节点的时候,此时恰好k的这位为0,那么就加上那一位上s[i]^1方向的所有跑过的数字的数量

Ps:为什么从高位到低位,要是有人不明白就按照上面的方法看看吧!然后你会发现因为高位的值的不确定导致你不能判断。

}

于是乎我们就可以开始写代码了。

Ps:这题的数组大小开到1<<24就好了(本菜鸡之前因为数组开小wa成傻逼)

 #include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
struct Trie
{
const static int range=;
const static int maxn=<<;///字典树大小
struct node
{
int next[range];
int cnt;///存该节点的经过数字之和
} Trienode[maxn];
int size;
void init()
{
memset(Trienode[].next,,sizeof(Trienode[].next));
Trienode[].cnt=;
size=;
}
void insert(int s)
{
int now=;
for(int i=; i>=; i--)///存31位
{
int c=(s>>i)&;
if(!Trienode[now].next[c])///没有该节点就开辟
{
memset(Trienode[size].next,,sizeof(Trienode[size].next));
Trienode[size].cnt=;
Trienode[now].next[c]=size++;
}
now=Trienode[now].next[c];///往后存
Trienode[now].cnt++;///这个数字经过了该节点,cnt++,因为第一个节点不算,所以说是先往后走再cnt++
}
}
int find(int s, int k)
{
int now=,i, ans=;
for(i=; i>=; i--)///找30位
{
int c=(s>>i)&, key=(k>>i)&;///c:存s[i]的第i位, key:存k的第i位
if(!key&&Trienode[now].next[c^])///如果key=0的时候,参照上面的分析
ans+=Trienode[Trienode[now].next[c^]].cnt;
if(Trienode[now].next[c^key])///往s[i]^K的方向越走越远
now=Trienode[now].next[c^key];
else
break;///没路
}
if(i==-)///跑完30~0的加上最后一位,其他的则是s[i]^K本身不存在
ans+=Trienode[now].cnt;
return ans;
}
} tree;
int ss[];
int main()
{
int n, k;
long long ans=;///答案会爆long long
tree.init( );
tree.insert();///为什么要插入0呢? 因为前i项异或和等于s[i]^0,这样就可以不用特判
ss[]=;///因为ss[i]^0=ss[i],用在输入ss[i]时
scanf("%d%d", &n, &k);
for(int i=; i<=n; i++)
{
scanf("%d", &ss[i]);
ss[i]^=ss[i-];///处理异或前缀和
ans+=tree.find(ss[i], k);///先找
tree.insert(ss[i]);///再查
}
printf("%I64d\n", ans);
}

菜鸡代码

Codeforces 665E. Beautiful Subarrays (字典树)的更多相关文章

  1. Educational Codeforces Round 12 E. Beautiful Subarrays 字典树

    E. Beautiful Subarrays 题目连接: http://www.codeforces.com/contest/665/problem/E Description One day, ZS ...

  2. E. Beautiful Subarrays 字典树

    http://codeforces.com/contest/665/problem/E 给定一个序列,问其中有多少个区间,所有数字异或起来 >= k 看到异或,就应该想到异或的性质,A^B^B ...

  3. codeforces 665E Beautiful Subarrays

    题目链接 给一个数列, 让你找出异或结果大于等于k的子序列的个数. 因为任意一段序列的异或值都可以用前缀异或和来表示, 所以我们先求出前缀异或和. 我们考虑字典树, 对于每一个前缀sum, 我们先查询 ...

  4. codeforces 665E E. Beautiful Subarrays(trie树)

    题目链接: E. Beautiful Subarrays time limit per test 3 seconds memory limit per test 512 megabytes input ...

  5. 【Codeforces】665E Beautiful Subarrays

    E. Beautiful Subarrays time limit per test: 3 seconds memory limit per test: 512 megabytes input: st ...

  6. Choosing The Commander CodeForces - 817E (01字典树+思维)

    As you might remember from the previous round, Vova is currently playing a strategic game known as R ...

  7. Codeforces 948D Perfect Security(字典树)

    题目链接:Perfect Security 题意:给出N个数代表密码,再给出N个数代表key.现在要将key组排序,使key组和密码组的亦或所形成的组字典序最小. 题解:要使密码组里面每个数都找到能使 ...

  8. Codeforces 655E Beautiful Subarrays【01trie树】

    题目链接: http://codeforces.com/contest/665/problem/E 题意: 求异或值大于给定K的区间个数. 分析: 首先我们可以得到区间前缀的异或值. 这样我们将这个前 ...

  9. Codeforces 282E Sausage Maximization(字典树)

    题目链接:282E Sausage Maximization 题目大意:给定一个序列A.要求从中选取一个前缀,一个后缀,能够为空,当时不能重叠.亦或和最大. 解题思路:预处理出前缀后缀亦或和,然后在字 ...

随机推荐

  1. C# 事件总线 EventBus

    1. 引言 事件总线这个概念对你来说可能很陌生,但提到观察者(发布-订阅)模式,你也许就很熟悉.事件总线是对发布-订阅模式的一种实现.它是一种集中式事件处理机制,允许不同的组件之间进行彼此通信而又不需 ...

  2. flink ha zk集群迁移实践

    flink为了保证线上作业的可用性,提供了ha机制,如果发现线上作业失败,则通过ha中存储的信息来实现作业的重新拉起. 我们在flink的线上环境使用了zk为flink的ha提供服务,但在初期,由于资 ...

  3. delphi 中如何执行SqlParameter形式的SQL语句

    procedure TForm1.Button1Click(Sender: TObject); begin ADOConnection1.Open('); ADOQuery1.Close; ADOQu ...

  4. 洛谷 P1495 曹冲养猪

    这是一道标准的孙子定理的题,题意浅显,思路明确 然后我就交了整整16遍啊,欺负人啊,题解暴力就能过,我就TLE ..悲惨的提交记录 下面是题面 题目描述 自从曹冲搞定了大象以后,曹操就开始捉摸让儿子干 ...

  5. 【刷题】洛谷 P4142 洞穴遇险

    题目背景 ZRQ在洞穴中准备采集矿物的时候遇险了!洞穴要塌了! 题目来源:zhoutb2333 题目描述 整个洞穴是一个 \(N*N\) 的方格图,每个格子形如 \((X,Y),1 \le X,Y \ ...

  6. [AT2364] [agc012_d] Colorful Balls

    题目链接 AtCoder:https://agc012.contest.atcoder.jp/tasks/agc012_d 洛谷:https://www.luogu.org/problemnew/sh ...

  7. CF954F Runner's Problem(动态规划,矩阵快速幂)

    CF954F Runner's Problem(动态规划,矩阵快速幂) 题面 CodeForces 翻译: 有一个\(3\times M\)的田野 一开始你在\((1,2)\)位置 如果你在\((i, ...

  8. Hive(一)基础知识

    一.Hive的基本概念 (安装的是Apache hive 1.2.1) 1.hive简介 Hive 是基于 Hadoop 的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表, 并提供类 SQ ...

  9. Linux之Json20160705

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.JSON采用完全独立于语言的文本格式,这些特性使JSON成为理想的数据交换语言.易于人阅读和编写,同时也易 ...

  10. Oracle 解决【ORA-01704:字符串文字太长】(转)

    错误提示:oracle在toad中执行一段sql语句时,出现错误‘ORA-01704:字符串文字太长’.如下图: 原因:一般为包含有对CLOB字段的数据操作.如果CLOB字段的内容非常大的时候,会导致 ...