洛谷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 }

 

posted @ 2017-06-27 14:52  third2333  阅读(210)  评论(0编辑  收藏  举报