線段樹主要的優勢是在將一個線性的數組轉換成一棵樹,從而減少大量的重復操作,并且在樹中的節點保存一些信息,以便更好的統計!它的各個操作的復雜度都是在logn的,而且我們知道,對于n個節點來說,最多是只有2n-1個樹的節點,另外對于一個如果有maxn個節點,那么我們知道最多要用4*maxn個樹的節點,這個可以證明

Poj2828 插入隊列,在這個過程中,后一個人可能會覆蓋前一個人,那么如何用線段樹來解呢,我們知道線段樹的葉子節點代表的就是當個節點的值,這里,我們把樹的節點表示空位的大小,那么在他插入的時候,然后從后面開始插入,那么如果前面出現重復的,那么因為空位數減少了,那么他們也會插在后面,插入的根據是根據空位的大俠來的,這個更新可以這樣寫

 Void update(int p,int l,int r,int rt)

{

  當前節點的空位數減少1

  如果p此時比他左孩子節點的空位數大,那么在往有孩子插入,此時空位數p-tree[mid].v

  否則,遍歷左孩子
}

Hdoj 1754 要求的是一段區間的最大值,這個在更新的時候,要不斷更新父子節點,另外在查詢的時候,其實對于每一次,最后的來的值總是從葉子節點的來的,只不過利用二分的思想,讓他每次都舍棄了一半的選擇!

code

Hdoj1698 hook,這題是用了懶惰標記,要求的問題是在一段區間了進行了某一個操作,然后求整個操作后,總共的和是多少

 懶惰的標記是指如果在更新的過程中,父子節點已經被全部覆蓋,那么作為他的孩子節點也坐上同樣的標記,這個思想是可以用這樣,首先判斷當前節點有沒被完全覆蓋,若是,則進行懶惰標記,對于他的所有孩子節點都是如此

code

Hdoj 3577這題的大意就是 火車有k個座位,乘客可以買從ab的車票,給你一些乘客的買票需求,要你求的就是哪些乘客能夠買到票 

  這題用的是線段樹,我們知道最好的情況是在每一條路線上能夠充分的用上,也就是被完全覆蓋,那么在判段許可的時候,如果此段已經被覆蓋過,那么不行!這里有一個問

題就是,因為有多個座位,所以每個座位都有一條路線,然后按照上述的思想進行處理即可

問題:第一次wa,是因為這里沒注意更新的區間應該是[a,b-1],因為我到了b站之后,就從這站下來了,然后下一次是可以從b站出發的 

code

Poj2528 這一題就是一些海報,要求的是最后沒有被完全覆蓋的海報總數, 那么怎么求呢,一個問題就是如果我們按照從一開始的數據進行處理的話,那么前一張海報可能會被后一張海報完全覆蓋,那么最后的結果就無法有效求出,那么我們可以反過來,那就是從最上面的海報開始,那么判斷這段區間內是否已經被完全覆蓋過,若是,則不用加1,否則加1

 這題先用離散化,將大的數據映射到比較小的數字上面,然后,根據離散后的數據我們可以得出,現在的問題就是,如何求,才能夠去掉被完全覆蓋的區間,那么這里我們建立一個hash,這個hash存放的值是表示第i個海報,如果查詢的當前的節點的記錄值,在hash表里沒有被記錄過,那么說明此區間沒有被完全覆蓋,

 現在證明這樣做的正確性,首先如果前一張海報被后一張覆蓋的情況,那么由于更新后的cnt[]的域記錄的也是后一張海報的離散化值,那么就不會記錄錯誤

  總結上面的過程,這個題目的總體思路就是輸入數據后,離散處理,在針對每一個進行更新,最后查詢,代碼待更新。。