新年彩灯Ⅰ

题意

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;
}
posted @ 2018-11-12 16:43  ChunhaoMo  阅读(165)  评论(0)    收藏  举报