# 解题思路

这题不难,但是原谅我一开始的傻逼想法,一会儿再给大家透露透露。

先说怎么做这题。

显然对于 $0$ 和 $1$ 来说,异或无非也就只有两种变化

  • 异或了奇数次,$0$ 就会变成 $1$,$1$ 就会变成 $0$。
  • 异或了偶数次,$0$ 和 $1$ 都不变。

那只需要在下传标记的时候下传修改了几次就可以。

好,下面说说我那傻逼的操作。我在下传标记的时候没有给子节点的 sum 进行异或,而是只下传了标记,并且在回溯的时候没有更新父节点的 sum 值。

然后我成功的没过样例,然鹅这并不傻逼,改过来就行了吗,对吧,但是,傻逼的来了,我改的时候没有按照上面的来改,而是在进行更新时,沿途将节点打一个flag标记,假装这一段区间需要更改。

哈哈哈哈哈,然后我成功的获得了 T 四个点的好成绩。

什么鬼,我居然忘记更新父节点,果然还是我太菜了。

我决定还是把这个代码放上吧。

# 附上代码

放上我的傻逼错误代码

  1. #include <iostream>
  2. #include <cstring>
  3. #include <cstdio>
  4. using namespace std;
  5. int n, m;
  6. const int maxn = 2e5+;
  7. struct node {int l, r, sum, t, tag, flag;}tree[maxn << ];
  8. struct Tree {
  9. #define Lson (k << 1)
  10. #define Rson ((k << 1) | 1)
  11. template <typename T> inline void read(T &x) {
  12. x = ; T f = ; char c = getchar();
  13. while (c < '' || c > '') {if(c == '-') f = -; c = getchar();}
  14. while (c <= '' && c >= '') {x = x* + c-''; c = getchar();}
  15. x *= f;
  16. }
  17. void build(int k, int ll, int rr) {
  18. tree[k].l = ll, tree[k].r = rr;
  19. tree[k].flag = tree[k].t = ;
  20. if(tree[k].l == tree[k].r) {
  21. scanf("%1d", &tree[k].sum);
  22. return ;
  23. }
  24. int mid = (tree[k].l + tree[k].r) >> ;
  25. build(Lson, tree[k].l, mid);
  26. build(Rson, mid+, tree[k].r);
  27. tree[k].sum = tree[Lson].sum + tree[Rson].sum;
  28. }
  29. void push_down(int k) {
  30. tree[Lson].t += tree[k].tag;
  31. tree[Rson].t += tree[k].tag;
  32. tree[Lson].tag += tree[k].tag;
  33. tree[Rson].tag += tree[k].tag;
  34. tree[k].tag = ;
  35. }
  36. void update(int k, int L, int R) {
  37. if(tree[k].l >= L && tree[k].r <= R) {
  38. tree[k].t ++;
  39. tree[k].tag ++;
  40. return;
  41. }
  42. tree[k].flag = ;
  43. if(tree[k].tag) push_down(k);
  44. int mid = (tree[k].l + tree[k].r) >> ;
  45. if(L <= mid) update(Lson, L, R);
  46. if(R > mid) update(Rson, L, R);
  47. }
  48. int query(int k, int L, int R) {
  49. int ans = ;
  50. if(tree[k].l >= L && tree[k].r <= R && tree[k].flag == ) {
  51. if(tree[k].t % == ) return (tree[k].r-tree[k].l+)-tree[k].sum;
  52. else return tree[k].sum;
  53. }
  54. if(tree[k].tag) push_down(k);
  55. int mid = (tree[k].l + tree[k].r) >> ;
  56. if(L <= mid) ans += query(Lson, L, R);
  57. if(R > mid) ans += query(Rson, L, R);
  58. return ans;
  59. }
  60. Tree () {
  61. read(n), read(m);
  62. build(, , n);
  63. int opt, l, r;
  64. for(int i=; i<=m; i++) {
  65. read(opt), read(l), read(r);
  66. if(opt == ) update(, l, r);
  67. else printf("%d\n", query(, l, r));
  68. }
  69. }
  70. }T;
  71. int main() {return ;}

好,我们再来看看正确的代码

  1. #include <iostream>
  2. #include <cstring>
  3. #include <cstdio>
  4. using namespace std;
  5. int n, m;
  6. const int maxn = 2e5+;
  7. struct node {int l, r, sum, t, tag, flag;}tree[maxn << ];
  8. struct Tree {
  9. #define Lson (k << 1)
  10. #define Rson ((k << 1) | 1)
  11. template <typename T> inline void read(T &x) {
  12. x = ; T f = ; char c = getchar();
  13. while (c < '' || c > '') {if(c == '-') f = -; c = getchar();}
  14. while (c <= '' && c >= '') {x = x* + c-''; c = getchar();}
  15. x *= f;
  16. }
  17. void build(int k, int ll, int rr) {
  18. tree[k].l = ll, tree[k].r = rr;
  19. tree[k].flag = tree[k].t = ;
  20. if(tree[k].l == tree[k].r) {
  21. scanf("%1d", &tree[k].sum);
  22. return ;
  23. }
  24. int mid = (tree[k].l + tree[k].r) >> ;
  25. build(Lson, tree[k].l, mid);
  26. build(Rson, mid+, tree[k].r);
  27. tree[k].sum = tree[Lson].sum + tree[Rson].sum;
  28. }
  29. void push_down(int k) {
  30. if(tree[k].tag % == )
  31. tree[Lson].sum = (tree[Lson].r-tree[Lson].l+)-tree[Lson].sum,
  32. tree[Rson].sum = (tree[Rson].r-tree[Rson].l+)-tree[Rson].sum;
  33. tree[Lson].tag += tree[k].tag;
  34. tree[Rson].tag += tree[k].tag;
  35. tree[k].tag = ;
  36. }
  37. void update(int k, int L, int R) {
  38. if(tree[k].l >= L && tree[k].r <= R) {
  39. tree[k].tag ++;
  40. tree[k].sum = (tree[k].r-tree[k].l+)-tree[k].sum;
  41. return;
  42. }
  43. if(tree[k].tag) push_down(k);
  44. int mid = (tree[k].l + tree[k].r) >> ;
  45. if(L <= mid) update(Lson, L, R);
  46. if(R > mid) update(Rson, L, R);
  47. tree[k].sum = tree[Lson].sum + tree[Rson].sum;
  48. }
  49. int query(int k, int L, int R) {
  50. int ans = ;
  51. if(tree[k].l >= L && tree[k].r <= R)
  52. return tree[k].sum;
  53. if(tree[k].tag) push_down(k);
  54. int mid = (tree[k].l + tree[k].r) >> ;
  55. if(L <= mid) ans += query(Lson, L, R);
  56. if(R > mid) ans += query(Rson, L, R);
  57. return ans;
  58. }
  59. Tree () {
  60. read(n), read(m);
  61. build(, , n);
  62. int opt, l, r;
  63. for(int i=; i<=m; i++) {
  64. read(opt), read(l), read(r);
  65. if(opt == ) update(, l, r);
  66. else printf("%d\n", query(, l, r));
  67. }
  68. }
  69. }T;
  70. int main() {return ;}

「 Luogu P2574 」 XOR的艺术——线段树的更多相关文章

  1. luogu P2574 XOR的艺术 (线段树)

    luogu P2574 XOR的艺术 (线段树) 算是比较简单的线段树. 当区间修改时.\(1 xor 1 = 0,0 xor 1 = 1\)所以就是区间元素个数减去以前的\(1\)的个数就是现在\( ...

  2. 洛谷 P2574 XOR的艺术(线段树 区间异或 区间求和)

    To 洛谷.2574 XOR的艺术 题目描述 AKN觉得第一题太水了,不屑于写第一题,所以他又玩起了新的游戏.在游戏中,他发现,这个游戏的伤害计算有一个规律,规律如下 1. 拥有一个伤害串为长度为n的 ...

  3. LOJ 2991 「THUSC 2016」补退选——trie+线段树合并或vector

    题目:https://loj.ac/problem/2291 想了线段树合并的做法.就是用线段树维护 trie 的每个点在各种时间的操作. 然后线段树合并一番,线段树维护前缀最大值,就是维护最大子段和 ...

  4. 【LOJ6620】「THUPC 2019」不等式 / inequality(线段树)

    点此看题面 大致题意: 给你两个长度为\(n\)的数组\(a_i\)和\(b_i\),定义\(f_k(x)=\sum_{i=1}^k|a_ix+b_i|\),对于\(k=1\sim n\)的每个\(f ...

  5. 【LOJ】#3109. 「TJOI2019」甲苯先生的线段树

    LOJ#3109. 「TJOI2019」甲苯先生的线段树 发现如果枚举路径两边的长度的话,如果根节点的值是$x$,左边走了$l$,右边走了$r$ 肯定答案会是$(2^{l + 1} + 2^{r + ...

  6. 【洛谷P2574】XOR的艺术

    XOR的艺术 题目链接 用线段树维护sum, 修改时 tag[p]^=1; sum=r-l+1-sum; 详见代码 #include<iostream> #include<cstdi ...

  7. 「Luogu 3792」由乃与大母神原型和偶像崇拜

    更好的阅读体验 Portal Portal1: Luogu Description 给你一个序列\(a\) 每次两个操作: 修改\(x\)位置的值为\(y\): 查询区间\([l, r]\)是否可以重 ...

  8. loj#2312. 「HAOI2017」八纵八横(线性基 线段树分治)

    题意 题目链接 Sol 线性基+线段树分治板子题.. 调起来有点自闭.. #include<bits/stdc++.h> #define fi first #define se secon ...

  9. 「POI2011 R2 Day2」Tree Rotations【线段树合并】

    题目链接 [BZOJ] [洛谷] [LOJ] 题解 由于是前序遍历,那么讨论一棵树上的逆序对的情况. 两个节点都在左子树上 两个节点都在右子树上 两个节点分别在不同的子树上. 前两种情况其实也可以归结 ...

随机推荐

  1. django QQ认证登录

    一.开发环境 django 1.10.2 python3.5.2 django-social-auth 0.3.6 二.申请QQ互联 APPID及SECRECT_KEY 大致步骤: 1.成为QQ互联开 ...

  2. SCUT - 254 - 欧洲爆破 - 概率dp - 状压dp

    https://scut.online/p/254 思路很清晰,写起来很恶心. #include<bits/stdc++.h> using namespace std; #define l ...

  3. (2)javascript的基本语法、数据结构、变量

    本篇学习资料主要讲解javascript的基本语法.数据结构.变量      无论是传统的编程语言,还是脚本语言,都具有数据类型.常量和变量.运算符.表达式.注释语句.流程控制语句等基本元素构成,这些 ...

  4. jqgrid 分级标题

    参考地址:http://www.trirand.com/jqgridwiki/doku.php?id=wiki:groupingheadar Grouping of the header should ...

  5. Milking Grid POJ - 2185 || 最小覆盖子串

    Milking Grid POJ - 2185 最小覆盖子串: 最小覆盖子串(串尾多一小段时,用前缀覆盖)长度为n-next[n](n-pre[n]),n为串长. 当n%(n-next[n])==0时 ...

  6. 解决 Cordova命令突然无法使用问题.

    问题背景 之前一直在做 Cordova 方面, 然后准备自己尝试使用 Vue + WebPack 再配合 Cordova 做一个 App . 更新了 npm , 然后然后, 我的 cordova 这个 ...

  7. linux的目录结构详细介绍

    linux的目录结构详细介绍 1. /目录(根目录) 2./ect/目录 特定主机系统范围内的配置文件. 3./usr/目录 默认软件都会存于该目录下.用于存储只读用户数据的第二层次:包含绝大多数的用 ...

  8. 利用uiautomator实现Android移动app启动时间的测试

    为了减少因手工测试的反应误差,这里介绍下如何利用Android自带的自动化测试工具uiautomator实现app启动时间的测试. 测试基本思路如下: 1.启动前记录当前的时间戳 2.启动app,直至 ...

  9. HDU 4565 So Easy! 数学 + 矩阵 + 整体思路化简

    http://acm.hdu.edu.cn/showproblem.php?pid=4565 首先知道里面那个东西,是肯定有小数的,就是说小数部分是约不走的,(因为b限定了不是一个完全平方数). 因为 ...

  10. 前端之CSS创建的样式

    CSS即层叠样式表,在创建时有以下几种样式: 1.内联样式(行内样式.行间样式): <标记 style=“属性:属性值:”></标记> 2.内部样式(嵌入式样式): <s ...