codevs 1690 开关灯 线段树水题

没什么好说的,标记put表示开关是否开着。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100003;
int sum[N<<2];
bool put[N<<2];
void pushdown(int l,int r,int rt)
{
    if (put[rt])
    {
        put[rt]=0;
        put[rt<<1]=!put[rt<<1];
        put[rt<<1|1]=!put[rt<<1|1];
        int mid=(l+r)>>1;
        sum[rt<<1]=mid-l+1-sum[rt<<1];
        sum[rt<<1|1]=r-mid-sum[rt<<1|1];
    }
}
void add(int L,int R,int l,int r,int rt)
{
    if (L<=l&&r<=R)
    {
        sum[rt]=r-l+1-sum[rt];
        put[rt]=!put[rt];
        return;
    }
    int mid=(l+r)>>1;
    pushdown(l,r,rt);
    if (L<=mid) add(L,R,l,mid,rt<<1);
    if (R>mid) add(L,R,mid+1,r,rt<<1|1);
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
int quest(int L,int R,int l,int r,int rt)
{
    if (L<=l&&r<=R)
     return sum[rt];
    int mid=(l+r)>>1,ans=0;
    pushdown(l,r,rt);
    if (L<=mid) ans+=quest(L,R,l,mid,rt<<1);
    if (R>mid) ans+=quest(L,R,mid+1,r,rt<<1|1);
    return ans;
}
int main()
{
    int i,n,m,x,y,z;
    scanf("%d %d
",&n,&m);
    memset(sum,0,sizeof(sum));
    memset(put,0,sizeof(put));
    for (i=1;i<=m;++i)
    {
        scanf("%d %d %d
",&x,&y,&z);
        if (x==0) add(y,z,1,n,1);
        else printf("%d
",quest(y,z,1,n,1));
    }
    return 0;
}

这样就可以了。

原文地址:https://www.cnblogs.com/abclzr/p/5137352.html