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 }
  • 相关阅读:
    ArcGIS Engine 笔记-控件类型
    个人简历(公开版)
    生活垃圾处理相关
    如何让nextcloud支持avi文件在线播放
    NextCloud前端支持播放mov文件
    使用Huginn抓取Discourse论坛
    使用WordPress制作微信小程序
    Github 快速建库上传本地代码
    BestSync多终端文件资料同步利器
    ABAP-SAP HANA 数据库并发控制
  • 原文地址:https://www.cnblogs.com/hxer/p/5563215.html
Copyright © 2011-2022 走看看