SPOJ7259(Light Switching)

数学模型:

维持一个01序列,支持2种操作:

1、将给定区间内的数取反;

2、查询给定区间内1的个数。

这题就是“暑假集训每日一题0712”的简化版

View Code
#include <stdio.h>

#define N 100001

int n,m,ans;

int sum[4*N],rev[4*N];

void update(int cur)

{

    int ls=cur<<1,rs=cur<<1|1;

    sum[cur]=sum[ls]+sum[rs];

}

void pushdown(int cur,int x,int y)

{

    int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1;

    if(rev[cur])

    {

        sum[ls]=mid-x+1-sum[ls];

        sum[rs]=y-mid-sum[rs];

        rev[ls]^=1;

        rev[rs]^=1;

        rev[cur]=0;

    }

}

void build(int cur,int x,int y)

{

    int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1;

    sum[cur]=rev[cur]=0;

    if(x==y)    return;

    build(ls,x,mid);

    build(rs,mid+1,y);

}

void reverse(int cur,int x,int y,int s,int t)

{

    int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1;

    if(x>=s && y<=t)

    {

        rev[cur]^=1;

        sum[cur]=y-x+1-sum[cur];

        return;

    }

    pushdown(cur,x,y);

    if(mid>=s)  reverse(ls,x,mid,s,t);

    if(mid+1<=t)    reverse(rs,mid+1,y,s,t);

    update(cur);

}

void query(int cur,int x,int y,int s,int t)

{

    int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1;

    if(x>=s && y<=t)

    {

        ans+=sum[cur];

        return;

    }

    pushdown(cur,x,y);

    if(mid>=s)  query(ls,x,mid,s,t);

    if(mid+1<=t)    query(rs,mid+1,y,s,t);

}

int main()

{

    int i,opt,x,y;

    while(~scanf("%d%d",&n,&m))

    {

        build(1,1,n);

        for(i=0;i<m;i++)

        {

            scanf("%d%d%d",&opt,&x,&y);

            if(opt)

            {

                ans=0;

                query(1,1,n,x,y);

                printf("%d\n",ans);

            }

            else    reverse(1,1,n,x,y);

        }

    }

    return 0;

}

你可能感兴趣的:(switch)