HDU 3308 LCIS 線段樹 區間合併

2021-10-06 12:17:31 字數 2323 閱讀 7977

鏈結lcis

題意 :

查詢區間 中最長的連續上公升序列,支援單點修改。

思路:

線段樹+區間合併,主要在於 pushup 和query 的變化。

需要記錄每個區間左右端點的數值,和以左右端點為起點的最長合法區間。

先看看 pushup ,當前區間的最大合法區間 首先可以由左右區間的最大值更新而來,同時如果左區間最右邊的數比右區間最左邊的數小,是可以進行一些合併操作的。具體看**

void

pushup

(int rt,

int m)

if(s[rt<<1|

1].rcnt==

(m>>1)

) s[rt]

.ncnt=

max(s[rt]

.ncnt,s[rt<<1]

.rcnt+s[rt<<1|

1].lcnt)

;//最長區間可能為兩區間合併部分

}}

update 部分沒有很大的變化,注意更新後要把值初始化為 1.

void

update

(int id,

int v,

int l,

int r,

int rt)

int mid=

(l+r)

>>1;

if(id<=mid)

update

(id,v,l,mid,rt<<1)

;if(id>mid)

update

(id,v,mid+

1,r,rt<<1|

1);pushup

(rt,r-l+1)

;}

最後就是 查詢操作了,這裡最大合法區間除了可能單獨在左右子區間,還有可能在兩個部分。

int

query

(int l,

int r,

int l,

int r,

int rt)

return ans;

}

完整**

#include

#include

#include

#include

#include

#include

#include

using

namespace std;

typedef

long

long ll;

const

int maxn=

1e5+7;

int t;

struct nodes[maxn<<2]

;void

pushup

(int rt,

int m)

if(s[rt<<1|

1].rcnt==

(m>>1)

) s[rt]

.ncnt=

max(s[rt]

.ncnt,s[rt<<1]

.rcnt+s[rt<<1|

1].lcnt);}

}void

build

(int l,

int r,

int rt)

int m=

(l+r)

>>1;

build

(l,m,rt<<1)

;build

(m+1

,r,rt<<1|

1);pushup

(rt,r-l+1)

;}void

update

(int id,

int v,

int l,

int r,

int rt)

int mid=

(l+r)

>>1;

if(id<=mid)

update

(id,v,l,mid,rt<<1)

;if(id>mid)

update

(id,v,mid+

1,r,rt<<1|

1);pushup

(rt,r-l+1)

;}intquery

(int l,

int r,

int l,

int r,

int rt)

return ans;

}int

main()

}}

HDU 3308 LCIS(線段樹合併)

維護乙個區間的包含最左的元素的lcis,包含最右元素的lcis,以及整個區間的lcis,然後pushup的時候就更新這三個值就行了。注意要考慮左右兒子可以 接 起來的情況等等 查詢的時候要注意,也要考慮左右可以 接 起來時候,不過還要注意,有可能左右兒子邊界的已經 越界了 就是超過了查詢範圍,還要取...

HDU 3308 LCIS(線段樹區間合併)

給你乙個序列,現在進行一些操作,一種是詢問某一段最長連續上公升子串行 lcis 的長度,另乙個就是修改某個點的值 區間合併的簡單題 這裡的區間合併,要判斷的是左兒子最右邊的值和右兒子最左邊的值的關係,那麼我們這道題要維護的東西就有 最左端開始的lcis,包括最右端的lcis,該區間的lcis,最左邊...

HDU 3308 LCIS 線段樹 區間合併

題目鏈結 前言 最近在做線段樹的練習,對於區間合併問題不是很清楚,花了好久才把線段樹的區間合併問題理清楚,所以把學習的過程記錄下來,建議手動建樹並模擬測試用例 題目大意 有乙個陣列,求這個陣列中最長的單調連續遞增序列的長度 題解 見一下注釋 樹結點的定義 有該結點的左端點 右端點 有該結點對應區間的...