P3870 [TJOI2009]开关 线段树 异或

  

题目描述

现有N(2 ≤ N ≤ 100000)盏灯排成一排,从左到右依次编号为:1,2,......,N。然后依次执行M(1 ≤ M ≤ 100000)项操作,操作分为两种:第一种操作指定一个区间[a, b],然后改变编号在这个区间内的灯的状态(把开着的灯关上,关着的灯打开),第二种操作是指定一个区间[a, b],要求你输出这个区间内有多少盏灯是打开的。灯在初始时都是关着的。

输入输出格式

输入格式:

第一行有两个整数N和M,分别表示灯的数目和操作的数目。接下来有M行,每行有三个整数,依次为:c, a, b。其中c表示操作的种类,当c的值为0时,表示是第一种操作。当c的值为1时表示是第二种操作。a和b则分别表示了操作区间的左右边界(1 ≤ a ≤ b ≤ N)。

输出格式:

每当遇到第二种操作时,输出一行,包含一个整数:此时在查询的区间中打开的灯的数目。

输入输出样例

输入样例#1:  复制
4 5
0 1 2
0 2 4
1 2 3
0 2 4
1 1 4
输出样例#1:  复制
1
2

可以用异或 见代码
因为一开始亮的灯数为0 所以不用build
#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define inf 0x3f3f3f3f
#define lson l,m,pos<<1
#define rson m+1,r,pos<<1|1
const int N=100000+5;
ll sum[N<<2],col[N<<2];

void up(int pos)
{
    sum[pos]=sum[pos<<1]+sum[pos<<1|1];
}
void down(int pos,int m)
{
    if(col[pos])
    {
        col[pos<<1]^=1;//每个下传懒标记进行异或   因为负负得正
        col[pos<<1|1]^=1;
        sum[pos<<1]=(m-(m>>1))-sum[pos<<1];//正常修改
        sum[pos<<1|1]=(m>>1)-sum[pos<<1|1];
        col[pos]=0;
    }
}
void update(int L,int R,int l,int r,int pos)
{
    if(L<=l&&r<=R)
    {
        col[pos]^=1;//不能改成1! 
        sum[pos]=r-l+1-sum[pos];
        return ;
    }
    int m=(l+r)>>1;
    down(pos,r-l+1);
    if(L<=m)
        update(L,R,lson);
    if(R>m)
        update(L,R,rson);
    up(pos);
}
int query(int L,int R,int l,int r,int pos)//正常讯问
{
    if(L<=l&&r<=R)
        return sum[pos];
    down(pos,r-l+1);
    int ans=0;
    int m=(l+r)>>1;
    if(L<=m)ans+=query(L,R,lson);
    if(R>m)ans+=query(L,R,rson);
    return ans;
}

int main()
{
    int n,m;
    RII(n,m);
    rep(i,1,m)
    {
        int a,b,c;RIII(a,b,c);
        if(a)
            cout<<query(b,c,1,n,1)<<endl;
        else update(b,c,1,n,1);
    }
    return 0;
}
View Code
 
 

猜你喜欢

转载自www.cnblogs.com/bxd123/p/10841336.html