题目链接

题意 : 中文题

分析 :

首先引入两篇写的很好的题解

题解一题解二

听说这种和异或相关区间求和的问题都尽量按位考虑

首先第一问、按二进制位计贡献的话、那么对于第 k 位而言

其贡献 = 区间异或和第 k 位为 1 的子区间个数 * 2^k

而能产生贡献的子区间必定满足 xorSum(R) ^ xorSum(L-1) 第 k 位为 1

注 : xorSum 为前缀异或和

要快速计算这个东西其实很简单、先计算出 xorSum

然后枚举右端点 R 、累计到目前为止每个位的 0 和 1 的数量

就能做到 O(1) 转移

假设 xorSum(R) 的第 k 位为 0

那么其贡献就应该为前面所有累计的 1 的数量  * 2^k

第二问就稍许复杂了些、但大体思路也是使用按位计贡献的思路

如果一个区间的所有子区间之和的第 k 位为 1 的话、那么所有子区间的和

在第 k 位上为 1 的子区间个数应当为奇数

也就是说 PreSum(R) - PreSum(L-1) 第 k 位为 1、这样子的二元组 (L、R) 有奇数个

注 : PreSum(i) 为前缀和

“PreSum(R) - PreSum(L-1) 第 k 位为 1”

这句话可以用一个不等式来表示

( PreSum(R) - PreSum(L-1) ) mod (2^(k+1)) ≥ 2^k

( 假设最后一位为第 0 位、即 k 从 0 开始算 )

原理可以这样子思考、你想你在十进制下截取一个数的后 k 位用什么办法?

是不是直接 mod 10^(k+1) ( 假设最后一位为第 0 位 )

二进制下也是一样的道理

不过模数涉及到减法就可能产生负数、需要对结果另加模数

那么对上述式子进行变形、有两种满足条件

可以发现如果枚举右端点的话、那么就是统计满足条件的 PreSum(L-1) mod 2^(k+1) 的个数了

那么由于是不等关系、那么可以先离散化所有的 PreSum(L-1) mod 2^(k+1) 值

存进去树状数组中便可轻易统计数量

不过与其算出数量再来判断奇偶、官方题解给出了更为巧妙的实现方法

也是用到了异或的性质、把树状数组存的值变成前缀异或和

那么如果查询的异或和是 1 那么说明是奇数、否则是偶数、可以看程序去体会一下

有一点要注意、就是离散的值都是 PreSum[i] mod 2^(k+1)

所以在二分查找的时候、可能不会在离散化后的数组里面找到相对应的值

那么要将它的贡献放入树状数组当中的话就要二分查找出一个 ≤ 它的位置、然后去异或 1

#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long

#define scl(i) scanf("%lld", &i)
#define scll(i, j) scanf("%lld %lld", &i, &j)
#define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k)
#define scllll(i, j, k, l) scanf("%lld %lld %lld %lld", &i, &j, &k, &l)

#define scs(i) scanf("%s", i)
#define sci(i) scanf("%d", &i)
#define scd(i) scanf("%lf", &i)
#define scIl(i) scanf("%I64d", &i)
#define scii(i, j) scanf("%d %d", &i, &j)
#define scdd(i, j) scanf("%lf %lf", &i, &j)
#define scIll(i, j) scanf("%I64d %I64d", &i, &j)
#define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k)
#define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k)
#define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k)
#define sciiii(i, j, k, l) scanf("%d %d %d %d", &i, &j, &k, &l)
#define scdddd(i, j, k, l) scanf("%lf %lf %lf %lf", &i, &j, &k, &l)
#define scIllll(i, j, k, l) scanf("%I64d %I64d %I64d %I64d", &i, &j, &k, &l)

#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define lowbit(i) (i & (-i))
#define mem(i, j) memset(i, j, sizeof(i))

#define fir first
#define sec second
#define VI vector<int>
#define ins(i) insert(i)
#define pb(i) push_back(i)
#define pii pair<int, int>
#define VL vector<long long>
#define mk(i, j) make_pair(i, j)
#define all(i) i.begin(), i.end()
#define pll pair<long long, long long>

#define _TIME 0
#define _INPUT 0
#define _OUTPUT 0
clock_t START, END;
void __stTIME();
void __enTIME();
void __IOPUT();
using namespace std;

;
;

int n;
int ans1;
int xorSum[maxn];
int c[maxn];
int arr[maxn];
LL id[maxn];
LL PreSum[maxn];
LL ans2;
LL one[maxn][];
LL zero[maxn][];

inline void BitAdd(int i)
{
    ){
        c[i] ^= ;
        i += lowbit(i);
    }
}

int BitSum(int i)
{
    ) ;
    ;
    ){
        ret ^= c[i];
        i -= lowbit(i);
    }return ret;
}

int idx(LL key)
{
    , R = n;
    ;///过滤掉负数的情况、key<0 <=> ret+1 = 0
                 ///在树状数组里面不产生贡献
    while(L <= R){
        ;
        ;
        ;
    };
}

int main(void){__stTIME();__IOPUT();

    sci(n);

    ; i<=n; i++){
        sci(arr[i]);
        xorSum[i] = xorSum[i-] ^ arr[i];
        PreSum[i] = PreSum[i-] + arr[i];
    }

    ; i<; i++) zero[][i] = 1LL;
    ; i<=n; i++){
        ; j<; j++){
            one[i][j] = one[i-][j];
            zero[i][j] = zero[i-][j];
            if((xorSum[i] & (1LL<<j))){
                one[i][j]++;
                ans1 += zero[i-][j] * 1LL * (1LL<<j) % mod;
                if(ans1 >= mod) ans1 -= mod;
            }else{
                zero[i][j]++;
                ans1 += one[i-][j] * 1LL * (1LL<<j) % mod;
                if(ans1 >= mod) ans1 -= mod;
            }
        }
    }

    ; (1LL<<j)<=PreSum[n]; j++){
        ;
        ; i<=n; i++)
            id[i] = PreSum[i] & ((1LL << j + ) - );

        sort(id, id+n+);

        mem(c, );
        ; i<=n; i++){
            LL cur = PreSum[i] & ((1LL<< j + ) - );
            BitAdd(idx(cur));
            res ^= BitSum(idx(cur - (1LL<<j))) ^
                   BitSum(idx(cur + (1LL<<j))) ^
                   BitSum(idx(cur));
        }
        if(res) ans2 |= 1LL << j;
    }

    printf("%d %lld\n", ans1, ans2);

__enTIME();;}

void __stTIME()
{
    #if _TIME
        START = clock();
    #endif
}

void __enTIME()
{
    #if _TIME
        END = clock();
        cerr<<"execute time = "<<(double)(END-START)/CLOCKS_PER_SEC<<endl;
    #endif
}

void __IOPUT()
{
    #if _INPUT
        freopen("in.txt", "r", stdin);
    #endif
    #if _OUTPUT
        freopen("out.txt", "w", stdout);
    #endif
}

BZOJ 4017 小 Q 的无敌异或 ( 树状数组、区间异或和、区间异或和之和、按位计贡献思想 )的更多相关文章

  1. bzoj 4017: 小Q的无敌异或

    4017: 小Q的无敌异或 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 593  Solved: 197[Submit][Status][Discu ...

  2. BZOJ 3744: Gty的妹子序列 【分块 + 树状数组 + 主席树】

    任意门:https://www.lydsy.com/JudgeOnline/problem.php?id=3744 3744: Gty的妹子序列 Time Limit: 20 Sec  Memory ...

  3. [BZOJ 3295] [luogu 3157] [CQOI2011]动态逆序对(树状数组套权值线段树)

    [BZOJ 3295] [luogu 3157] [CQOI2011] 动态逆序对 (树状数组套权值线段树) 题面 给出一个长度为n的排列,每次操作删除一个数,求每次操作前排列逆序对的个数 分析 每次 ...

  4. BZOJ.2738.矩阵乘法(整体二分 二维树状数组)

    题目链接 BZOJ 洛谷 整体二分.把求序列第K小的树状数组改成二维树状数组就行了. 初始答案区间有点大,离散化一下. 因为这题是一开始给点,之后询问,so可以先处理该区间值在l~mid的修改,再处理 ...

  5. BZOJ.3110.[ZJOI2013]K大数查询(整体二分 树状数组/线段树)

    题目链接 BZOJ 洛谷 整体二分求的是第K小(利用树状数组).求第K大可以转为求第\(n-K+1\)小,但是这样好像得求一个\(n\). 注意到所有数的绝对值\(\leq N\),将所有数的大小关系 ...

  6. BZOJ 2738 子矩阵第k大 | 二维树状数组 整体二分 分治

    BZOJ 2738 "矩阵乘法"(子矩阵第k大) 题意 给出一个矩阵,多次询问子矩阵中第k大的数是多少. 题解 我做这道题之前先照着这道题出了一道题,是这道题的一维版本,在这里:h ...

  7. Bzoj4548 小奇的糖果(链表+树状数组)

    题面 Bzoj 题解 很显然,我们只需要考虑单独取线段上方的情况,对于下方的把坐标取反再做一遍即可(因为我们只关心最终的答案) 建立树状数组维护一个横坐标区间内有多少个点,维护双向链表实现查询一个点左 ...

  8. bzoj 4372 烁烁的游戏——动态点分治+树状数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4372 和 bzoj 3070 震波 是一个套路.注意区间修改的话,树状数组不能表示 dis ...

  9. BZOJ 3289: Mato的文件管理[莫队算法 树状数组]

    3289: Mato的文件管理 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 2399  Solved: 988[Submit][Status][Di ...

随机推荐

  1. 17.Letter Combinations of a Phone Number (char* 和 string 相互转化)

    leetcode 第17题 分析 char*和string相互转化 char*(或者char)转string 可以看看string的构造函数 default (1) string(); copy (2 ...

  2. Python面向对象中的继承、多态和封装

    Python面向对象中的继承.多态和封装 一.面向对象的三大特性 封装:把很多数据封装到⼀个对象中,把固定功能的代码封装到⼀个代码块, 函数,对象, 打包成模块. 这都属于封装思想. 继承:⼦类可以⾃ ...

  3. 第十三章 ZYNQ-MIZ701 TIMER定时器中断

      上篇文章实现了了PS接受来自PL的中断,本片文章将在ZYNQ的纯PS里实现私有定时器中断.每隔一秒中断一次,在中断函数里计数加1,通过串口打印输出. 本文所使用的开发板是Miz701 PC 开发环 ...

  4. PB做的托盘程序(最小化后在左下角显示图标)

    见‘文件’资源

  5. 彭博社:博通正在与赛门铁克洽谈收购事宜(博通能买得起 又能讲故事的 没几个了 为了刺激资本的兴趣 只能瞎搞 就和intel 收购 麦咖啡一样。就像杜蕾斯收购美赞臣一样,也许只是纯粹的商业行为,哪行赚钱干哪行)

    彭博社今日消息,知名芯片制造商 Broadcom 公司正在就收购网络安全公司 Symantec 事宜进行高级会谈,因为 Broadcom 希望寻找半导体业务之外的机会,以实现多元化经营. 据称,在彭博 ...

  6. python 定时爬取内容并发送报告到指定邮箱

    import requests import smtplib import schedule import time from bs4 import BeautifulSoup from email. ...

  7. IOC+EF+Core项目搭建IOC注入及框架(二)

    配置ServiceCollection /// <summary> /// 表示IServiceCollection的扩展 /// </summary> public stat ...

  8. SpringBoot的启动配置原理

    一.启动流程 创建SpringApplication对象 public class SpringApplication { public SpringApplication(Class... prim ...

  9. java进程被OOM干掉问题记录

    异常现象:用户环境部署了一台iserver,访问一阵后,进程没了   分析: 1.bin目录下没有崩溃日志,在tomcat的访问日志里面也没有看到有用的信息.iserver.log里面也没有信息 2. ...

  10. idea控制台乱码修改

    我的idea当前版本是2019.2.2 试了很多,只有这个有效果 工具类→HELP→Edit Custom VM OPtions中加 -Dfile.encoding=utf-8 然后重启IDEA 这个 ...