您的位置:首页 > 其它

【线段树】【重庆省选2006】简单题 easy

2013-01-23 10:52 441 查看
简单题(easy)
 

有一个n个元素的数组,每个元素初始均为0。有m条指令,要么让其中一段连续序列数字反转——0变1,1变0(操作1),要么询问某个元素的值(操作2)。例如当n=20时,10条指令如下:

 

操作

回答

操作后的数组

1 1 10

N/A

11111111110000000000

2 6

1

11111111110000000000

2 12

0

11111111110000000000

1 5 12

N/A

11110000001100000000

2 6

0

11110000001100000000

2 15

0

11110000001100000000

1 6 16

N/A

11110111110011110000

1 11 17

N/A

11110111111100001000

2 12

1

11110111111100001000

2 6

1

11110111111100001000

 

【输入文件】

输入文件easy.in第一行包含两个整数n,m,表示数组的长度和指令的条数,以下m行,每行的第一个数t表示操作的种类。若t=1,则接下来有两个数L,R(L<=R),表示区间[L,R]的每个数均反转;若t=2,则接下来只有一个数I,表示询问的下标。

 

【输出文件】

    每个操作2输出一行(非0即1),表示每次操作2的回答。

 

【样例】

easy.in

easy.out

20 10
1 1 10
2 6
2 12
1 5 12
2 6
2 15
1 6 16
1 11 17
2 12
2 6
1

0

0

0

1

1

 

 

【限制】

50%的数据满足:1<=n<=1,000,1<=m<=10,000

100%的数据满足:1<=n<=100,000,1<=m<=500,000

这一题的题目描述很明显,线段树

用一个sum[]数组来统计翻转的次数(奇数次翻转后为1,偶数次为0)

第一次写线段树。。。。。

C++ Code

/*
C++ Code http://blog.csdn.net/jiangzh7 By Jiangzh
*/
#include<cstdio>

int n,m;
int sum[4*100000+10];

void read()
{
freopen("easy.in","r",stdin);
freopen("easy.out","w",stdout);

scanf("%d%d",&n,&m);
}

void change(int p,int l,int r,int x,int y)
{
if(x<=l && r<=y) {sum[p]++;return;}

int m=(l+r)>>1;
if(x<=m) change(p<<1,l,m,x,y);//左儿子中有涉及
if(y>m) change((p<<1)+1,m+1,r,x,y);//右儿子中有涉及
}

int count(int p,int l,int r,int x)
{
if(l==r && x==l) return sum[p]&1;

int ans=sum[p];
int m=(l+r)>>1;
if(x<=m) {ans+=count(p<<1,l,m,x); return ans&1;}
if(x>m) {ans+=count((p<<1)+1,m+1,r,x); return ans&1;}
}

void work()
{
for(int i=1;i<=m;i++)
{
int op,x,y;
scanf("%d",&op);
if(op==1)
{
scanf("%d%d",&x,&y);
change(1,1,n,x,y);
}
else{
scanf("%d",&x);
printf("%d\n",count(1,1,n,x));
}
}
}

int main()
{
read();
work();
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: