新年将至,YY准备挂一排彩灯,已知彩灯刚挂完的彩灯共有N盏(编号为1,2,3,……),并且都是灭的。彩灯的闪烁由一段程序控制。
每一秒钟程序会生成两个正整数a和b(1<=a,b<=N),然后将编号为a和b之间的所有灯的状态改变一次,即如果灯i是灭的,那么经过一次改变,灯i会亮,如果灯i是亮的,经过一次改变,灯i会灭。
当YY看着自己挂的彩灯不断闪烁的时候,问题来了,YY想知道任意时刻某一区间灯的状态。
多组测试数据,每一组第一行是一个整数N(1<=N<=1000000)和一个整数M(1<=M<=3000)。
然后是M行数据,包括以下两种形式:
1 a b 表示灯a和灯b之间的灯(含灯a和灯b)变换一次状态。
0 x y 表示YY想知道此刻灯x到灯y(包含灯x和灯y)的状态.
对于每次YY想知道结果的时候,输出一行灯的状态(编号小的灯优先),如果是亮的输出”1”,否则输出”0”;
3 3 1 1 2 1 2 3 0 1 3
101
分析
给你一串灯泡,然后有m次操作,
要么是对一片区域里的灯泡状态进行一次修改,
要么是输出一个区域里的所有灯泡的状态。
如果是仅仅实现这个功能其实并不复杂
代码如下
#include
#define maxn 1000005
using namespace std;
int a[maxn],b[maxn],c[maxn];
int n,m;
int main()
{
while(cin>>n>>m)
{
int x,y,z;
memset(a,0,sizeof(a));
首先将所有灯泡都关上
for(int i=0;i>x>>y>>z;
if(y>z)
swap(y,z);
if(x==1)
{
for(int i=y;i<=z;i++)
{
if(a[i]==0)
a[i]=1;
else
a[i]=0;
改变所有目标区域的灯泡的状态
}
}
else
for(int i=y;i<=z;i++)
cout<
是不是很简单,
然后我成功超时了
为什么呐
因为不论是修改操作还是输出操作时间复杂度都是O(n),总的时间复杂度就是O(m*n);
所以这个代码理所当然的超时了。
然后有什么办法呐,
当然就是用树状数组
树状数组干同样的事复杂度却是O(M*lgN),
别小看这个lg,很大的数一lg就很小了,
这个学过数学的都知道吧,不需要我说了。
#include
#define maxn 1000005
using namespace std;
int a[maxn];
int n,m;
void update(int p,int x)
{
while(p<=maxn)
{
a[p]+=x;
p+=p&-p;
}
}
void range_update(int l, int r,int x)
{
update(l,x);
update(r + 1,-x);
}
int query(int p)
{
int res = 0;
while (p) res += a[p], p -= p & -p;
return res;
}
int main()
{
while(cin>>n>>m)
{
int x,y,z;
memset(a,0,sizeof(a));
for(int i=0;i>x>>y>>z;
if(y>z)
swap(y,z);
if(x==1)
range_update(y,z,1);
else
{
for(int j=y;j<=z;j++)
{
int t=query(j);
if(t%2)
printf("1");
else
printf("0");
}
printf("\n");
}
}
}
return 0;
}