洛谷P2574 XOR的艺术 线段树 区间修改 区间求和询问
洛谷P2574 XOR的艺术
线段树 区间修改 区间求和询问
关于线段树的空间问题
线段树 一般来说都是要四倍空间的,当然你也可以动态开点
然后我这道题因为姿势不大妙 ,然后空间需要八倍才能过,然后一直RE
后来我发现了问题所在
当区间询问 区间修改到达也叶节点 是不用再向下面推标记了的,
因为lazy 标记表示的是当前这个节点已经处理过了,然后他的儿子还没有处理过,
因为是叶节点,所以他的儿子自然是不用再处理的,因为叶节点是没有儿子的,所以
自然就不用再下推标记了
如果叶节点还下推标记,那就需要八倍空间了
所以我们先判是不是叶节点 是的话就直接更新 然后就退出
不是在 下推标记 ,这样空间就稳定是 4 倍了
1 #include <cstdio> 2 #include <cmath> 3 #include <cstdlib> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iomanip> 8 #include <iostream> 9 using namespace std ; 10 11 const int maxn = 200011 ; 12 char s[maxn] ; 13 struct node{ 14 int l,r,sum,xr ; 15 }tree[4*maxn]; 16 int n,Q,type,ans ; 17 18 inline int read() 19 { 20 char ch = getchar() ; 21 int x = 0 ,f = 1 ; 22 while(ch<'0'||ch>'9') { if(ch=='-') f = -1 ; ch = getchar() ; } 23 while(ch>='0'&&ch<='9') { x = x*10+ch-48 ; ch = getchar() ; } 24 return x*f ; 25 } 26 27 inline void pushup(int root) 28 { 29 tree[root].sum = tree[root*2].sum + tree[root*2+1].sum ; 30 } 31 32 inline void pushdown(int root) 33 { 34 tree[root*2].xr^=1 ; 35 tree[root*2].sum = ( tree[root*2].r - tree[root*2].l+1 ) -tree[root*2].sum ; 36 tree[root*2+1].xr^=1 ; 37 tree[root*2+1].sum = (tree[root*2+1].r - tree[root*2+1].l +1 ) - tree[root*2+1].sum ; 38 tree[root].xr = 0 ; 39 } 40 41 inline void updata(int l,int r,int root) 42 { 43 if(tree[root].l==l&&tree[root].r==r) 44 { 45 tree[root].sum = (tree[root].r - tree[root].l + 1 ) - tree[root].sum ; 46 tree[root].xr^=1 ; 47 return ; 48 } 49 50 if(tree[root].xr) pushdown(root) ; 51 52 int mid = ( tree[root].l + tree[root].r ) /2 ; 53 if( r<=mid ) updata(l,r,root*2) ; 54 else if(l>mid) updata(l,r,root*2+1) ; 55 else { 56 updata(l,mid,root*2) ; 57 updata(mid+1,r,root*2+1) ; 58 } 59 pushup(root) ; 60 } 61 62 inline int query(int l,int r,int root) 63 { 64 if(tree[root].l==l&&tree[root].r==r) 65 return tree[root].sum ; 66 67 if(tree[root].xr) pushdown(root) ; // 先判断是否为叶节点然后再 下推标记 68 69 int mid = ( tree[root].l + tree[root].r ) /2 ; 70 if( r<=mid ) return query(l,r,root*2) ; 71 else if(l>mid) return query(l,r,root*2+1) ; 72 else{ 73 int ans = 0 ; 74 ans+=query(l,mid,root*2) ; 75 ans+=query(mid+1,r,root*2+1) ; 76 return ans ; 77 } 78 79 } 80 81 inline void build(int l,int r,int root) 82 { 83 tree[root].l = l ; 84 tree[root].r = r ; 85 if(l==r) 86 { 87 tree[root].sum = s[ l ] - 48 ; tree[root].xr = 0 ; 88 return ; 89 } 90 int mid = (l+r) / 2 ; 91 build(l,mid,root*2) ; 92 build(mid+1,r,root*2+1) ; 93 pushup(root) ; 94 } 95 96 int main() 97 { 98 n = read() ; Q = read() ; 99 scanf("%s",s+1) ; 100 build(1,n,1) ; 101 int x,y ; 102 for(int i=1;i<=Q;i++) 103 { 104 type = read() ; x = read() ; y = read() ; 105 if(type==0) 106 updata(x,y,1) ; 107 else 108 { 109 ans = query(x,y,1) ; 110 printf("%d\n",ans) ; 111 } 112 } 113 return 0 ; 114 }