新年彩灯Ⅰ

题意

Description
新年将至,YY准备挂一排彩灯,已知彩灯刚挂完的彩灯共有N盏(编号为1,2,3,……),并且都是灭的。彩灯的闪烁由一段程序控制。

每一秒钟程序会生成两个正整数a和b(1<=a,b<=N),然后将编号为a和b之间的所有灯的状态改变一次,即如果灯i是灭的,那么经过一次改变,灯i会亮,如果灯i是亮的,经过一次改变,灯i会灭。

当YY看着自己挂的彩灯不断闪烁的时候,问题来了,YY想知道任意时刻某一区间灯的状态。

Input
多组测试数据,每一组第一行是一个整数N(1<=N<=1000000)和一个整数M(1<=M<=3000)。

然后是M行数据,包括以下两种形式:

         1 a b 表示灯a和灯b之间的灯(含灯a和灯b)变换一次状态。

         0 x y 表示YY想知道此刻灯x到灯y(包含灯x和灯y)的状态.

Output
对于每次YY想知道结果的时候,输出一行灯的状态(编号小的灯优先),如果是亮的输出”1”,否则输出”0”;

Sample Input
3 3 1 1 2 1 2 3 0 1 3

Sample Output
101

分析

就是个树状数组&&差分
每当对一个区间[l,r]进行修改,只需要进行add(l,x)和add(r+1,-x) 因为要把没有修改的区间抵消
对于每次查询直接for求每一个位置的前缀和,就会得到该位置改变了多少次,奇数次就是1,偶数次就是0

代码

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int N=1e6+10;
int a[N];
int n,m;
void add(int i,int x)
{    int h=i;
    while(h<=n){
        a[h]+=x;
        h+=h&-h;
    }
}
void range_update(int l,int r,int x){
    add(l,x);
    add(r+1,-x);
}
int getqsum(int x){//对某个等操作的次数 
    int sum=0;
    while(x){
        sum+=a[x];
        x-=x&-x;
    }
    return sum;
}
int main(){
    int l,r,op;
    //freopen("in.txt","r",stdin);
    while(cin>>n>>m){
        memset(a,0,sizeof(a));
        while(m--){
            cin>>op>>l>>r;
            if(l>r) swap(l,r);
            if(op==1){
                range_update(l,r,1);
            }
            else{
                for(int i=l;i<=r;i++)
                cout<<getqsum(i)<<endl;
            }
        }
        cout<<endl;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/mch5201314/p/9947368.html