?
线段树很好的题。涉及到的知识点:lazy操作处理异或操作和置01,区间合并。
有五种操作:
0 a b 将[a,b]变为0
1 a b 将[a,b]变为1
2 a b 将[a,b]取反
3 a b 输出[a,b]的1的个数
4 a b 输出[a,b]内最长的连续1的个数
对区间的操作与poj 3225类似。置01与取反是互斥的,一段区间上只能有一个标记,discuss里面也说了取反的时候若递归到区间全为0或1的时候再取反违背了线段树的本质。因此对于这两个操作设置一个变量lazy,它的取值有-1,0,1,2,-1表示没有操作,0和1表示被0或1覆盖,2表示区间取反。因为两次取反后相当于没取,lazy标记在这里起到很大作用,若要对这个区间取反,只需将其lazy置为2,下次再取反时就变为原来的,即置为-1。
?
询问区间的1的个数时,只需要sum维护区间的和即可。求连续的1的长度时,需要区间合并,又因为有取反操作,同时还要记录区间内连续的0的个数。
?
?
#include
#include
#include