「 Luogu P2574 」 XOR的艺术——线段树
# 解题思路
这题不难,但是原谅我一开始的傻逼想法,一会儿再给大家透露透露。
先说怎么做这题。
显然对于 $0$ 和 $1$ 来说,异或无非也就只有两种变化
- 异或了奇数次,$0$ 就会变成 $1$,$1$ 就会变成 $0$。
- 异或了偶数次,$0$ 和 $1$ 都不变。
那只需要在下传标记的时候下传修改了几次就可以。
好,下面说说我那傻逼的操作。我在下传标记的时候没有给子节点的 sum 进行异或,而是只下传了标记,并且在回溯的时候没有更新父节点的 sum 值。
然后我成功的没过样例,然鹅这并不傻逼,改过来就行了吗,对吧,但是,傻逼的来了,我改的时候没有按照上面的来改,而是在进行更新时,沿途将节点打一个flag标记,假装这一段区间需要更改。
哈哈哈哈哈,然后我成功的获得了 T 四个点的好成绩。
什么鬼,我居然忘记更新父节点,果然还是我太菜了。
我决定还是把这个代码放上吧。
# 附上代码
放上我的傻逼错误代码
#include <iostream> #include <cstring> #include <cstdio> using namespace std; int n, m; const int maxn = 2e5+3; struct node {int l, r, sum, t, tag, flag;}tree[maxn << 2]; struct Tree { #define Lson (k << 1) #define Rson ((k << 1) | 1) template <typename T> inline void read(T &x) { x = 0; T f = 1; char c = getchar(); while (c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while (c <= '9' && c >= '0') {x = x*10 + c-'0'; c = getchar();} x *= f; } void build(int k, int ll, int rr) { tree[k].l = ll, tree[k].r = rr; tree[k].flag = tree[k].t = 0; if(tree[k].l == tree[k].r) { scanf("%1d", &tree[k].sum); return ; } int mid = (tree[k].l + tree[k].r) >> 1; build(Lson, tree[k].l, mid); build(Rson, mid+1, tree[k].r); tree[k].sum = tree[Lson].sum + tree[Rson].sum; } void push_down(int k) { tree[Lson].t += tree[k].tag; tree[Rson].t += tree[k].tag; tree[Lson].tag += tree[k].tag; tree[Rson].tag += tree[k].tag; tree[k].tag = 0; } void update(int k, int L, int R) { if(tree[k].l >= L && tree[k].r <= R) { tree[k].t ++; tree[k].tag ++; return; } tree[k].flag = 1; if(tree[k].tag) push_down(k); int mid = (tree[k].l + tree[k].r) >> 1; if(L <= mid) update(Lson, L, R); if(R > mid) update(Rson, L, R); } int query(int k, int L, int R) { int ans = 0; if(tree[k].l >= L && tree[k].r <= R && tree[k].flag == 0) { if(tree[k].t % 2 == 1) return (tree[k].r-tree[k].l+1)-tree[k].sum; else return tree[k].sum; } if(tree[k].tag) push_down(k); int mid = (tree[k].l + tree[k].r) >> 1; if(L <= mid) ans += query(Lson, L, R); if(R > mid) ans += query(Rson, L, R); return ans; } Tree () { read(n), read(m); build(1, 1, n); int opt, l, r; for(int i=1; i<=m; i++) { read(opt), read(l), read(r); if(opt == 0) update(1, l, r); else printf("%d\n", query(1, l, r)); } } }T; int main() {return 0;}
好,我们再来看看正确的代码
#include <iostream> #include <cstring> #include <cstdio> using namespace std; int n, m; const int maxn = 2e5+3; struct node {int l, r, sum, t, tag, flag;}tree[maxn << 2]; struct Tree { #define Lson (k << 1) #define Rson ((k << 1) | 1) template <typename T> inline void read(T &x) { x = 0; T f = 1; char c = getchar(); while (c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while (c <= '9' && c >= '0') {x = x*10 + c-'0'; c = getchar();} x *= f; } void build(int k, int ll, int rr) { tree[k].l = ll, tree[k].r = rr; tree[k].flag = tree[k].t = 0; if(tree[k].l == tree[k].r) { scanf("%1d", &tree[k].sum); return ; } int mid = (tree[k].l + tree[k].r) >> 1; build(Lson, tree[k].l, mid); build(Rson, mid+1, tree[k].r); tree[k].sum = tree[Lson].sum + tree[Rson].sum; } void push_down(int k) { if(tree[k].tag % 2 == 1) tree[Lson].sum = (tree[Lson].r-tree[Lson].l+1)-tree[Lson].sum, tree[Rson].sum = (tree[Rson].r-tree[Rson].l+1)-tree[Rson].sum; tree[Lson].tag += tree[k].tag; tree[Rson].tag += tree[k].tag; tree[k].tag = 0; } void update(int k, int L, int R) { if(tree[k].l >= L && tree[k].r <= R) { tree[k].tag ++; tree[k].sum = (tree[k].r-tree[k].l+1)-tree[k].sum; return; } if(tree[k].tag) push_down(k); int mid = (tree[k].l + tree[k].r) >> 1; if(L <= mid) update(Lson, L, R); if(R > mid) update(Rson, L, R); tree[k].sum = tree[Lson].sum + tree[Rson].sum; } int query(int k, int L, int R) { int ans = 0; if(tree[k].l >= L && tree[k].r <= R) return tree[k].sum; if(tree[k].tag) push_down(k); int mid = (tree[k].l + tree[k].r) >> 1; if(L <= mid) ans += query(Lson, L, R); if(R > mid) ans += query(Rson, L, R); return ans; } Tree () { read(n), read(m); build(1, 1, n); int opt, l, r; for(int i=1; i<=m; i++) { read(opt), read(l), read(r); if(opt == 0) update(1, l, r); else printf("%d\n", query(1, l, r)); } } }T; int main() {return 0;}
作者:Mystical-W
来源:http://www.cnblogs.com/bljfy
说明:客官~~您如果觉得写得好的话,记得给我点赞哦。如果要转载的请在合适的地方注明出处。谢
谢您的合作。您要是有什么有疑问的地方可以在下面给我评论。也可以直接私信我哦
声明:本作品由Mystical-W采用知识共享署名-非商业性使用-禁止演绎 4.0 国
际许可协议进行许可
来源:http://www.cnblogs.com/bljfy
说明:客官~~您如果觉得写得好的话,记得给我点赞哦。如果要转载的请在合适的地方注明出处。谢
谢您的合作。您要是有什么有疑问的地方可以在下面给我评论。也可以直接私信我哦
声明:本作品由Mystical-W采用知识共享署名-非商业性使用-禁止演绎 4.0 国
际许可协议进行许可