X or What?

符号约定:

  • $\xor$ 表示异或。
  • popcount($x$) 表示非负整数 $x$ 的二进制表示里数字 1 出现的次数。例如,$13 = 1101_2$,则 popcount(13) = 4。

注意到,popcount($a \xor b$) = popcount($a$) + popcount($b$) - 2 * number of positions both $a$ and $b$ are set。

因此,popcount($a \xor b$) 的奇偶性 = (popcount($a$) + popcount($b$)) 的奇偶性。

区间 $[L, R]$ 的异或和的 popcount 为偶数 $\iff$ $L - 1, R$ 这两个前缀的异或和的 popcount 同奇偶。

分别考虑异或和的 popcount 为奇数的前缀、异或和的 popcount 为偶数的前缀。

改变 $A_p$ 对答案的影响:

若 $A_p$ 的 popcount 的奇偶性不变,则答案亦不变,否则 $p, p+1, \dots, n - 1$ 这些前缀的异或和的 popcount 的奇偶性翻转。

解法 1

用线段树维护前缀的异或和的 popcount 的奇偶性。

支持查询:

  • 异或和的 popcount 为偶数的前缀最后一次出现的位置。
  • 异或和的 popcount 为奇数的前缀第一次/最后一次出现的位置。
  1. bool bit_even(int x) {
  2. return (__builtin_popcount(x) & 1) == 0;
  3. }
  4. struct node {
  5. int n[2];
  6. int flipped;
  7. void flip() {
  8. swap(n[0], n[1]);
  9. flipped ^= 1;
  10. }
  11. };
  12. const int N = 100005;
  13. node seg[4 * N];
  14. int sum[N];
  15. void push_up(int i) {
  16. int l = i * 2, r = l + 1;
  17. for (int j = 0; j < 2; j++) {
  18. seg[i].n[j] = seg[l].n[j] + seg[r].n[j];
  19. }
  20. }
  21. void build (int i, int l, int r) {
  22. seg[i].flipped = 0;
  23. if (l == r) {
  24. seg[i].n[0] = bit_even(sum[l]);
  25. seg[i].n[1] = 1 - seg[i].n[0];
  26. return;
  27. }
  28. int mid = (l + r) / 2;
  29. build(i * 2, l, mid);
  30. build(i * 2 + 1, mid + 1, r);
  31. push_up(i);
  32. }
  33. void push_down(int i) {
  34. if (seg[i].flipped) {
  35. int l = i * 2, r = i * 2 + 1;
  36. seg[l].flip();
  37. seg[r].flip();
  38. seg[i].flipped = 0;
  39. }
  40. }
  41. int find_first(int v, int i, int l, int r) {
  42. if (seg[i].n[v] == 0) return r + 1;
  43. if (l == r) return l;
  44. push_down(i);
  45. int mid = (l + r) / 2;
  46. int res = find_first(v, i * 2, l, mid);
  47. if (res <= mid) {
  48. return res;
  49. }
  50. return find_first(v, i * 2 + 1, mid + 1, r);
  51. }
  52. int find_last(int v, int i, int l, int r) {
  53. if (seg[i].n[v] == 0) return l - 1;
  54. if (l == r) return l;
  55. push_down(i);
  56. int mid = (l + r) / 2;
  57. int res = find_last(v, i * 2 + 1, mid + 1, r);
  58. if (res > mid) {
  59. return res;
  60. }
  61. return find_last(v, i * 2, l, mid);
  62. }
  63. void flip(int i, int l, int r, int ql, int qr) {
  64. if (ql > r || qr < l) return;
  65. if (ql <= l && r <= qr) {
  66. seg[i].flip();
  67. return;
  68. }
  69. int mid = (l + r) / 2;
  70. push_down(i);
  71. flip(i * 2, l, mid, ql, qr);
  72. flip(i * 2 + 1, mid + 1, r, ql, qr);
  73. push_up(i);
  74. }
  75. int main() {
  76. #ifdef LOCAL
  77. ifstream in("main.in");
  78. cin.rdbuf(in.rdbuf());
  79. #endif
  80. int T; cin >> T;
  81. for (int cas = 1; cas <= T; ++cas) {
  82. cout << "Case #" << cas << ":";
  83. int n, q; cin >> n >> q;
  84. vector<int> a(n + 1);
  85. for (int i = 1; i <= n; i++) {
  86. cin >> a[i];
  87. sum[i] = sum[i - 1] ^ a[i];
  88. }
  89. build(1, 1, n);
  90. while (q--) {
  91. int p, v;
  92. cin >> p >> v;
  93. ++p;
  94. if (bit_even(v) != bit_even(a[p])) {
  95. flip(1, 1, n, p, n);
  96. }
  97. a[p] = v;
  98. cout << " " << max(find_last(0, 1, 1, n), find_last(1, 1, 1, n) - find_first(1, 1, 1, n));
  99. }
  100. cout << endl;
  101. }
  102. return 0;
  103. }

Kick Start 2019 Round D的更多相关文章

  1. kick start 2019 round D T3题解

    ---恢复内容开始--- 题目大意:共有N个房子,每个房子都有各自的坐标X[i],占据每个房子需要一定花费C[i].现在需要选择K个房子作为仓库,1个房子作为商店(与题目不同,概念一样),由于仓库到房 ...

  2. kick start 2019 round D T2题解

    题目大意:由N个房子围成一个环,G个人分别顺时针/逆时针在房子上走,一共走M分钟,每分钟结束,每个人顺/逆时针走到相邻的房子.对于每个房子都会记录最后时刻到达的人(可能是一群人).最终输出每个人会被几 ...

  3. Kick Start 2019 Round A Contention

    $\DeclareMathOperator*{\argmax}{arg\,max}$ 题目链接 题目大意 一排 $N$ 个座位,从左到右编号 $1$ 到 $N$ . 有 $Q$ 个预定座位的请求,第 ...

  4. Kick Start 2019 Round H. Elevanagram

    设共有 $N = \sum_{i=1}^{9} A_i$ 个数字.先把 $N$ 个数字任意分成两组 $A$ 和 $B$,$A$ 中有 $N_A = \floor{N/2}$ 个数字,$B$ 中有 $N ...

  5. Kick Start 2019 Round A Parcels

    题目大意 $R \times C$ 的网格,格子间的距离取曼哈顿距离.有些格子是邮局.现在可以把至多一个不是邮局的格子变成邮局,问每个格子到最近的邮局的曼哈顿距离的最大值最小是多少. 数据范围 $ 1 ...

  6. Kick Start 2019 Round B Energy Stones

    对我很有启发的一道题. 这道题的解法中最有思维难度的 observation 是 For simplicity, we will assume that we never eat a stone wi ...

  7. 【DP 好题】Kick Start 2019 Round C Catch Some

    题目链接 题目大意 在一条数轴上住着 $N$ 条狗和一个动物研究者 Bundle.Bundle 的坐标是 0,狗的坐标都是正整数,可能有多条狗住在同一个位置.每条狗都有一个颜色.Bundle 需要观测 ...

  8. Kick Start 2019 Round F Teach Me

    题目链接 题目大意 有 $N$ 个人,$S$ 项技能,这些技能用 $1, 2, 3, \dots, S$ 表示 .第 $i$ 个人会 $c_i$ 项技能($ 1 \le c_i \le 5 $).对于 ...

  9. Google Kick Start 2019 C轮 第一题 Wiggle Walk 题解

    Google Kick Start 2019 C轮 第一题 Wiggle Walk 题解 题目地址:https://codingcompetitions.withgoogle.com/kickstar ...

随机推荐

  1. linux中more命令如何使用

         more命令,功能类似 cat ,cat命令是整个文件的内容从上到下显示在屏幕上.兄弟连Linux培训教程() more会以一页一页的显示方便使用者逐页阅读,而最基本的指令就是按空白键(sp ...

  2. javascript中创建对象的方式及优缺点(二)

    一.工厂模式 流程: 定义一个函数,函数返回对象. 适用场景: 需要创建多个对象,都是Object类型. 优点:完成了返回一个对象的要求. 缺点: 对象没有一个具体的类型,无法通过constructo ...

  3. CF1213D Equalizing by Division

    easy version hard version 问题分析 直接从hard version入手.不难发现从一个数\(x\)能得到的数个数是\(O(\log x)\)的.这样总共有\(O(n\log ...

  4. UE4添加模块

    添加模块在这篇文章里已经有详细的描述了: https://orfeasel.com/creating-custom-modules/ 但是这篇文章中少写了一个步骤: 最后要在 <工程名>E ...

  5. latex参考文献中作者名字含有特殊字符怎么办

  6. python中的事务

    1. 为什么要有事务 事务广泛的运用于订单系统.银行系统等多种场景 例如: A用户和B用户是银行的储户,现在A要给B转账500元,那么需要做以下几件事: 检查A的账户余额>500元: A 账户中 ...

  7. Docker入门-构建第一个Java程序

    定制镜像 准备一个没有第三方依赖的java web项目,可能参考示例maven结构项目: session-web.war 把该war上传到安装有docker软件的服务器上宿主目录下.在同级目录创建Do ...

  8. python3笔记十九:os和ospath模块

    一:学习内容 os模块 ospath模块 获取指定目录下所有文件和目录 二:os模块 包含了普遍的操作系统功能,需要导入该模块:import os 当前所在位置目录结构为: 目录操作 1.获取当前目录 ...

  9. vuex 的介绍

    vue-cli 中 css 的作用域 scoped vue 数据的为响应数据,一改全改,一变全变的特性,我们的很多处理也会围绕着他 vuex 是处理数据的,是 vue 的数据仓库 vuex 的作用:采 ...

  10. leetcode-easy-string-28 Implement strStr()

    mycode   77.15% class Solution(object): def strStr(self, haystack, needle): """ :type ...