zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 12 E. Beautiful Subarrays 预处理+二叉树优化

    链接:http://codeforces.com/contest/665/problem/E

    题意:求规模为1e6数组中,连续子串xor值大于等于k值的子串数;

    思路:xor为和模2的性质,所以先预处理之后,可以枚举这种确实子串区间的方法为O(n^2);

    优化?把每一个前缀xor扔到二叉树中,从根节点出发,以高位前缀值的二进制数构造一颗二叉树,这样就可以在构造的时候,实现对子树节点个数的求解;之后在线求解到当前节点的可选的前缀xor的个数,

    即以k为主线

    如果当前位k为1,则在前缀二叉树中只能找和当前节点xor出结果为1的节点,并且这个节点的num值不能加到结果中;

    如果是当前位k为0,则直接加上xor结果为1的节点个数(num),方向不变;

    注:最后一个叶子节点不能求到,要在最后加上叶子节点的个数

    时间复杂度为O(nlgn)

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 const int MAXN = 11234567;
     5 int num[MAXN],tot = 1,d[MAXN][2],n,k;
     6 void update(int a)
     7 {
     8     for(int i = 30, p = 1;i >= 0;i--){
     9         if(d[p][(a>>i)&1] == 0) d[p][(a>>i)&1] = ++tot;
    10         p = d[p][(a>>i)&1];
    11         num[p]++;
    12     }
    13 }
    14 long long solve(int x)
    15 {
    16     long long  ans = 0, p = 1;
    17     for(int i = 30;i >= 0;i--){
    18         if((k>>i)&1) p = d[p][1^((x>>i)&1)];
    19         else{
    20             ans += num[d[p][1^((x>>i)&1)]];
    21             p = d[p][(x>>i)&1];
    22         }
    23     }
    24     return ans + num[p]; // leaf
    25 }
    26 int main()
    27 {
    28     cin>>n>>k;
    29     int prefix = 0,x;
    30     long long ans = 0;
    31     for(int i = 0;i < n;i++){
    32         update(prefix);
    33         scanf("%d",&x);
    34         prefix ^= x;
    35         ans += solve(prefix);
    36     }
    37     printf("%I64d",ans);
    38 }
  • 相关阅读:
    Linux关闭You have new mail in /var/spool/mail/root提示
    表单验证提交内容不能为空的几种方法
    CSS选择器的优先级
    SQL Server BCP 资料导入导出
    软考数据库-系统开发与软件工程
    软考数据库-无损联接分解
    软考数据库-数据结构
    反转字符串, 以单词反转句子
    数组中是否存在两数之和等于目标值
    栈 (Swift数组实现栈)
  • 原文地址:https://www.cnblogs.com/hxer/p/5563215.html
Copyright © 2011-2022 走看看