?
一道题又做了一天。。这道题对我来说起初有N多难点。
1:区间的开闭如何解决。、
2:怎样把区间的交并补、对称差转化为对线段树的操作。
后来与实验室的同学讨论了后解决了前面两个问题。
对于区间的开闭,可以将区间放大一倍,偶数点表示端点,奇数点表示区间内线段,前开的话左端点加1,右开的话右端点减1。例如[1,3]可以表示成[2,6],(1,3)表示成(3,5)。
?
对于区间的交并补问题,可以转化为区间覆盖问题,若T区间为[a,b]。
U T:[a,b]覆盖为1.
I T:[0,a-1] [b+1,maxn] 覆盖为0
D T:[a,b]覆盖为0
C T:[0,a-1] [b+1,maxn] 覆盖为0,[a,b]取反
S T:[a,b]取反
?
然后处理区间的覆盖和异或操作。
起初对异或操作没想到lazy,考虑到异或的性质,两次异或相当于没变。所以节点附加两个信息:col,rev。
col表示覆盖信息,col=0说明全被覆盖为0,col=1说明全被覆盖为1,col=-1说明没有全被覆盖。
rev表示异或信息,rev=1说明区间整体异或,rev=0说明不用异或。
可见只有当col=-1时rev才有用。更新时,若是区间覆盖,相应区间覆盖后抹去异或操作,若是异或操作,判断区间是否完全覆盖,若是直接异或,否则rev进行异或。push_down的时候,若区间完全覆盖,将覆盖信息推送下去并将左右儿子的异或操作抹去,若区间没有完全覆盖,必定有异或操作,将左右儿子可以异或的异或掉,不能异或的将其rev异或。
?
?
#include
#include
#include
?