基礎線段樹 修改版

2021-08-06 03:23:03 字數 4727 閱讀 7253

網上流傳、通用的是另乙個版本,與我這乙個有所不同,我自己的第一印象就是這樣一種線段樹,也僅僅有一點不同而已,不過,這一種,更新資料的位置只需要寫一次就好,而網上那一種需要寫三次。

修改操作時,當前區間如果在修改區間內,則對當前區間操作,並把操作加到當前區間的lazy上,也就是,所有的lazy都是對他的兒子區間有效的,對自己的區間並無效。如果乙個區間的lazy不為空,並且要用到兒子區間,就要把lazy標籤傳給兒子區間,並同時對兒子區間的資料進行更新(也就是push_down函式),因為,有lazy標籤的區間一定是已經修改完成區間。 這樣,在加lazy時一次操作,在push_down裡對左右兒子操作,一共三處操作。

可以發現,這個版本很關鍵的一句話就是,有lazy標籤的區間一定已經修改完成,lazy標籤只對兒子區間有效。

這個版本相對去那個版本關鍵的那句話的是,有lazy標籤的區間一定沒有修改,lazy標籤只對自己區間有效。

既然所有操作都可以用lazy來表示(要不然懶惰標記怎麼對兒子區間操作呢?),那麼修改操作時,當前區間如果在修改區間內,則對當前區間加上lazy標籤,然後立即把lazy標籤傳遞兒子區間(也就是push_down函式)注1,在傳遞過程中,更新了這個區間的資料,傳遞lazy標籤給了兒子區間,清空這個區間的lazy標籤。 並且在修改操作時,只要當前區間有lazy,就要先push_down,一方面更新自己的資料,一方面傳遞lazy標籤。 這樣,所有更新資料都在push_down 函式內, 也就操作只需要寫一次。

毛老師版本

jianzs版本

思想帶有lazy標籤的區間一定已經修改完成。lazy只對兒子區間有效。

帶有lazy標籤的區間一定沒有修改。lazy只對當前區間有效。

push_down 位置

在需要遞迴兒子區間時呼叫,在modify_tree(lson….)和modify_tree(rson….)、 query(lson…)和query(rson…)的上面即可。

只要當前區間有lazy就需呼叫,也就是modify_tree 和 query 的第一行。注2

注1:因為如果不立即push_down,也就不更新當前區間的資料,那麼當回溯時,也就不更新父親區間的資料,那麼如果下次查詢父親區間的資料,就會出現錯誤。

注2:如果不在第一行,那麼這層函式的執行過程中,對當前區間查詢的資料都是不是最新的,也就不是正確的,所以錯誤,結果是乙個沒有處理lazy的錯誤結果。並且,在修改時,如果當前區間不在修改區間內,則會提前return,而這個節點的兄弟節點被修改,那麼回溯時父親節點maintian就會出現錯誤,這也就是說,只要在push_down後呼叫了兒子區間,那麼左右兒子必須呼叫push_down來更新自己的資料,以更新父親節點的資料。 所以放在函式第一行。

推薦乙個驗證自己板子正確性的地方。驗線段樹板子

/*

自己版本

如果乙個節點有lazy,說明這個節點沒有修改,直接標記了lazy,

應該更新這個節點,然後把lazy傳給子結點。

*/#include

#define lson (index<<1)

#define rson (index<<1|1)

#define mid ((l+r)>>1)

using

namespace

std;

const

int maxn = 1e6;

typedef

long

long ll;

struct node ;

node segtree[maxn<<2]; // 必須四倍,否則可能re

ll a[maxn]; // 葉子節點資料

int n, m; // n 葉子結點數量, m 運算元

// 用於維護父親節點資料。

// 對左右兒子節點修改後,需要重新對父親節點資料更新。

void maintain(int index)

void build_tree(int index, int l, int r)

build_tree(lson, l, mid);

build_tree(rson, mid+1, r);

maintain(index);

}// 主要操作, 也就是題目中對資料的操作,套用模版基本上修改這裡即可

void operate(int index, int l, int r)

void push_down(int index, int l, int r)

segtree[index].lazy = 0;}/*

modeify 先push_down,更新 index 的資料,

並且,如果[l,r],如果不在修改範圍[ql, qr],會呼叫兒子節點,

更新兒子節點就必須把它父親節點的lazy傳下去,不然就會錯誤。

*/void modify_tree(int index, int l, int r, int ql, int qr, int oper)

modify_tree(lson, l, mid, ql, qr, oper);

modify_tree(rson, mid+1, r, ql, qr, oper);

maintain(index);

/* 這的maintian 只對oper起作用,如果只是lazy處理,已經體

現在處理當前區間的lazy*/}/*

query 先 push_down,如果 [l,r] 在 [ql, qr] 內,需要返回最新的點的資料,

如果不在範圍,需要呼叫兒子節點,也就需要更新兒子節點的資訊,更新兒子節點

的資訊需要父親節點的lazy。

*/ll query(int index, int l, int r, int ql, int qr)

ll ans1 = query(lson, l, mid, ql, qr);

ll ans2 = query(rson, mid+1, r, ql, qr);

return ans1+ans2;

}void init()

int main()

build_tree(1, 1, n);

for(int i = 1; i <= m; i++) else

if(cmd == 1) else

if(cmd == 2) else

if(cmd == 3)

}return

0;}

/*

常見版本

如果乙個節點有lazy, 說明這個節點已經修改過,應該把lazy直接傳給子結點,

然後把子結點的資訊更新。

*/#include

#define lson (index<<1)

#define rson (index<<1|1)

#define mid ((l+r)>>1)

using

namespace

std;

const

int maxn = 1e6;

typedef

long

long ll;

struct node ;

node segtree[maxn<<2]; // 必須四倍,否則可能re

ll a[maxn]; // 葉子節點資料

int n, m; // n 葉子結點數量, m 運算元

// 用於維護父親節點資料。

// 對左右兒子節點修改後,需要重新對父親節點資料更新。

void maintain(int index)

void build_tree(int index, int l, int r)

build_tree(lson, l, mid);

build_tree(rson, mid+1, r);

maintain(index);

}// // 主要操作, 也就是題目中對資料的操作,套用模版基本上修改這裡即可

void operate(int index, int l, int r , int oper)

//只要要呼叫兒子節點,就呼叫push_down,

void push_down(int index, int l, int r)

void modify_tree(int index, int l, int r, int ql, int qr, int oper)

push_down(index, l, r);

modify_tree(lson, l, mid, ql, qr, oper);

modify_tree(rson, mid+1, r, ql, qr, oper);

maintain(index);

}ll query(int index, int l, int r, int ql, int qr)

push_down(index, l, r);

ll ans1 = query(lson, l, mid, ql, qr);

ll ans2 = query(rson, mid+1, r, ql, qr);

return ans1+ans2;

}void init()

int main()

build_tree(1, 1, n);

for(int i = 1; i <= m; i++) else

if(cmd == 1) else

if(cmd == 2) else

if(cmd == 3)

}return

0;}

我是蒟蒻,請多多指教

多檔案修改版

這是繼上乙個錯誤之後,張玉老師給修改的,一開始我的類物件宣告是全域性變數,所以多檔案了以後,求周長那裡就出了問題。這一版不但解決了問題,更是幫我省出了很大的空間,身為類成員的兩個函式代替了六個資料成員,留出了空間,程式也不那麼亂七八糟了。棒!程式 main 作 者 趙玲玲 完成日期 2014 年 4...

佛緣(結局修改版)

闌珊因不滿前一篇的結局部份,所有才有了這個補丁,當然得轉過來。闌珊的文字功底的確n8錯,似乎她可以去維護世界和平了,呵呵!佛緣 修改版sp20061006 我才知道佛祖的法力早已突飛猛進,塵世浮游,他都能看得一清二楚了,而我也在他的手上,看世事變遷,只是,無論如何,都回不到曾經平淡的心境了。曾幾何時...

模板匹配 Match Template 修改版

修改者 madturtle 對於王先生的版本進行了修改,因為有些地方不對。模板匹配的工作方式 模板匹配的工作方式跟直方圖的反向投影基本一樣,大致過程是這樣的 通過在輸入影象上滑 像塊對實際的影象塊和輸入影象進行匹配。假設我們有一張100x100的輸入影象,有一張10x10的模板影象,查詢的過程是這樣...