BZOJ 1230 开关灯

由于上手就做那种xor和cover混合、第二个就做树型转线性的xor,现在做这个。。。

可谓是给我一个xor的大彻大悟的机会啊!


由于孟神的指导。。。我的线段树,算是基本的入门了。。。

昂。。总结起来有以下几点:

懒惰标记跟本节点无关,因为懒惰标记到本节点之前,已经处理完本届点的值了。

也就是说,在pushdown过程中,要处理子节点的懒惰标记和值。

update到符合要求的节点的时候,要进行懒惰标记,同时处理本节点的值,

而que的时候,直接返回本节点的值就可以了。

而且,懒惰标记只能从上往下推,不能从下往上推。

也就是说,update过程中需要pushup,而que不需要。


最后是代码= = 。。。

#include<stdio.h>
#define lson l,mid,rt*2
#define rson mid+1,r,rt*2+1
#define X 100010
int a[X*4],sum[X*4],ll,rr;
void pushup(int rt){
    sum[rt]=sum[rt*2]+sum[rt*2+1];
}
void Xor(int l,int r,int rt){
    a[rt]^=1;
    sum[rt]=r-l+1-sum[rt];
}
void pushdown(int l,int r,int rt){
    if(a[rt]){
        a[rt]=0;
        int mid=l+r>>1;
        Xor(lson);
        Xor(rson);
    }
}
void update(int l,int r,int rt){
    if(ll<=l&&rr>=r){
        Xor(l,r,rt);
        return ;
    }
    pushdown(l,r,rt);
    int mid=l+r>>1;
    if(ll<=mid)update(lson);
    if(rr>mid)update(rson);
    pushup(rt);
}
int que(int l,int r,int rt){
    if(ll<=l&&rr>=r){
        return sum[rt];
    }
    pushdown(l,r,rt);
    int mid=l+r>>1,as=0;
    if(ll<=mid)as=que(lson);
    if(rr>mid)as+=que(rson);
    return as;
}
int main(){
    int i,j,n,m,f;
    while(~scanf("%d%d",&n,&m)){
        for(i=0;i<=4*n;i++)a[i]=sum[i]=0;
        for(i=0;i<m;i++){
            scanf("%d%d%d",&f,&ll,&rr);
            if(f)printf("%d\n",que(1,n,1));
            else update(1,n,1);
        }
    }
    return 0;
}


你可能感兴趣的:(BZOJ 1230 开关灯)