poj 3225 區間(區間的交並補操作)
一道題又做了一天。。這道題對我來說起初有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