SPOJ 7259 Light Switching (水题,区间01取反)

#include <iostream>
#include <stdio.h>
#include <algorithm>
#define lson rt<<1,L,mid
#define rson rt<<1|1,mid+1,R
/*
水题
题意:给出n个初始为0的数,有两种操作
      0 a b  将区间[a,b]取反
      1 a b  查询区间[a,b]中1的个数
*/
using namespace std;
const int maxn=100005;
int n,m;

struct Node{
    int num0,num1;  //统计该区间0和1的个数
    bool flag;
}tree[maxn<<2];

void pushUp(int rt){
    tree[rt].num0=tree[rt<<1].num0+tree[rt<<1|1].num0;
    tree[rt].num1=tree[rt<<1].num1+tree[rt<<1|1].num1;
}
void build(int rt,int L,int R){
    tree[rt].num0=R-L+1;
    tree[rt].num1=0;
    tree[rt].flag=false;
    if(L==R)
        return;
    int mid=(L+R)>>1;
    build(lson);
    build(rson);
    pushUp(rt);
}

void pushDown(Node &rt,Node &ls,Node &rs){
    if(rt.flag){
        ls.flag=!ls.flag;  //一开始将ls和rs的flag直接设为true了,导致WA。。。
        rs.flag=!rs.flag;
        swap(ls.num0,ls.num1);
        swap(rs.num0,rs.num1);
        rt.flag=false;
    }
}
void update(int rt,int L,int R,int l,int r){
    if(l<=L&&R<=r){
        tree[rt].flag=!tree[rt].flag;
        swap(tree[rt].num0,tree[rt].num1);
        return;
    }
    pushDown(tree[rt],tree[rt<<1],tree[rt<<1|1]);
    int mid=(R+L)>>1;
    if(l<=mid)
        update(lson,l,r);
    if(r>mid)
        update(rson,l,r);
    pushUp(rt);
}

int query(int rt,int L,int R,int l,int r){
    if(l<=L&&R<=r){
        return tree[rt].num1;
    }
    pushDown(tree[rt],tree[rt<<1],tree[rt<<1|1]);
    int mid=(L+R)>>1;
    int ret=0;
    if(l<=mid)
        ret+=query(lson,l,r);
    if(r>mid)
        ret+=query(rson,l,r);
    return ret;
}
int main()
{
    int t,a,b;
    scanf("%d%d",&n,&m);
    build(1,1,n);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&t,&a,&b);
        if(t==0){
            update(1,1,n,a,b);
        }
        else{
            printf("%d
",query(1,1,n,a,b));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/chenxiwenruo/p/3420260.html