【线段树】easy

来源:互联网 发布:mac安装找不到磁盘 编辑:程序博客网 时间:2024/06/06 18:18

重庆06省选题第一题水题

简单题(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第一行包含两个整数nm,表示数组的长度和指令的条数,以下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

 

很裸的线段树,一次就AC了。主要要想到就是统计区间的翻转次数,想不到这儿也不行。

用欧教的方法,用一个堆来维护线段树,就是做到“心中有树”啊,嘿嘿。

一开始卡在了一个地方,以为modify的时候要考虑多种情况:1、包含在左儿子里。2、包含在右儿子里。3、一部分在左儿子里,一部分在右儿子里。4、全部包含整个区间。最后决定打一遍来试试看,打到一半才发现第三种情况是包含在一二两种情况中的,这样子就减少了考虑的情况,也减少了编写的复杂度。

因此有种感觉就是,有时候并不一定要把所有的思路理清楚再开始做,有时候需要做一些快速但是很有效的小实验,可以快速地找到错误。

 

需要注意的一点是,最后查看一个点的翻转次数的时候,需要把它和所有的父亲的翻转次数都加起来,用一个回溯完成。因为在modify的时候,为了减少处理次数,降低时间复杂度,如果完全包含一个节点,就直接忽略它的所有子树,可以减少枚举量。

 

#include <cstdio>const long maxn = 100000;long sum[maxn*4+10];long n;long m;void modify(long l,long r,long ml,long mr,long p){ long m = (l+r)>>1; if (ml<=l&&mr>=r) {  sum[p] = (sum[p]+1)&1;  return; } if (ml<=m){modify(l,m,ml,mr,p<<1);} if (mr>m){modify(m+1,r,ml,mr,(p<<1)+1);}}long find(long l,long r,long x,long p){ if (l==r) {  return sum[p]&1; } long m = (l+r)>>1; if (x<=m){return (sum[p]+find(l,m,x,p<<1))&1;} if (x>m) {return (sum[p]+find(m+1,r,x,(p<<1)+1))&1;}}int main(){ freopen("easy.in","r",stdin); freopen("easy.out","w",stdout); scanf("%ld%ld",&n,&m); for (long i=1;i<m+1;i++) {  long a;  scanf("%ld",&a);  if (a==1)  {   long l;long r;   scanf("%ld%ld",&l,&r);   modify(1,n,l,r,1);  }  else  {   long x;   scanf("%ld",&x);   printf("%ld\n",find(1,n,x,1));  } } return 0;}


 

 

原创粉丝点击