快速操作序列$ⅱ$:給出乙個有$n$個元素的陣列$a_1,a_2,..,,a_n$,設計乙個資料結構支援以下兩種操作:
不難想到把$set$操作進行分解,記錄在結點中,但很快就會發現乙個問題,add操作的時間順序不會影響結果,但set會。比如先執行$add(1,4,1)$再執行$add(2,3,2)$等價於先執行$add(2,3,2)$再執行$add(1,4,1)$,但先執行$set(1,4,1)$再執行$set(2,3,2)$卻不等價於先執行$set()2,3,2($再執行$set(1,4,1)$。怎麼辦呢?
簡而言之,就是維護標記,包括標記下推和標記更新。當執行$update$操作時經過帶標記結點時,需要將標記傳推到左右子結點,同時消除自身的標記。$set$操作的標記更新很簡單,直接用新的$setv$覆蓋原來的$setv$。
值得注意的是,與之前的$add$操作相比,**中多了兩處$maintain$的呼叫。這是因為只要標記下傳,該子樹的附加資訊就必須重新計算,但是我們只進入其中乙個子樹,該子樹在遞迴訪問結束後自然會呼叫$maintain$,因此還需要針對不進行遞迴訪問的子樹呼叫$maintain$。
1void pushdown(into)2
8}910
void maintain(int o, int l, int
r)1118}
1920
intcl,cr,v;
21void update(int o, int l, int
r)22
31maintain(o, l, r);
32 }
查詢操作跟之前類似,不同的是,當兩個add操作存在祖先-後代關係時是進行累加,而當兩個set操作存在祖先-後代關係時,以祖先結點為準即可(為什麼?祖先結點的set肯定是後出現的)。
1intql, qr;
2int query(int o, int l, intr)3
14 }
線段樹(2)區間修改
快速序列操作i,給出乙個n個元素的陣列a1,a2,an,你的任務是設計乙個資料結構支援一下兩種操作 set l,r,v 把al,al 1,ar的值全部修改為v v 0 query l,r 計算子串行al,al 1,ar的元素和 最小值和最大值。include include using namesp...
線段樹002 區間修改
接下來講解一下區間修改 比如在下面這個圖中我要將1 5區間的值全都改為v 正常人的思維是把1 5這個區間的修改看成對點1,2,3,4,5的單點修改 但這樣的複雜度是nlog n 是比較高的 我們換一種想法,在修改區間的時候我們仍然像區間查詢一樣自上而下的尋找要修改的區間。那麼我們最後 找到區間是1 ...
模板 線段樹(2)區間修改
好像叫做懶操作來著。還是叫延遲修改更高大上一點吧 區間修改 兩種操作 add l r v 把a l a l 1 a r 的值全部增加v query l r 計算子串行a l a l 1 a r 的元素和,最小值和最大值 修改 查詢的範圍均為 y1,y2 維護節點o,它對應區間 l,r void ma...