洛谷P4198 樓房重建

2022-04-30 11:09:10 字數 1334 閱讀 7806

題意:給定序列,每次修改乙個值,求字首最大值的個數。

解:線段樹經典應用。

每個節點維護最大值和該區間字首最大值個數。

發現我們不用下傳標記,只需要合併區間。

需要實現乙個函式int ask([l r] lm)求出區間[l r]中前乙個數是lm時字首最大值個數。

那麼當lm >= large[ls]時,return ask([mid r] lm)

這個很好理解,左子區間的所有數都不會成為字首最大值。

當lm < large[ls]時,return ask([l mid] lm) + (sum[o] - sum[ls])

這個注意,不是sum[rs]因為sum[rs]的意義是從0開始,而這個的前面會有large[ls]擋著,所以是sum[o] - sum[ls]

修改的時候先一路到底把large值改了。然後return的時候把沿途區間都更新。

具體來說就是sum[o] = ask([l r] 0)...等等,好像有問題。

lm < large[ls]的時候,求值是要呼叫sum[o]的,這不就迴圈呼叫導致出錯了嗎?

所以寫成sum[o] = sum[ls] + ask([mid r] large[ls])即可。

本題不用建樹。需要建樹的時候就跟修改類似的寫法即可。

1 #include 2 #include 3

4const

int n = 100010;5

6double a[n], large[n << 2];7

int n, sum[n << 2];8

9int ask(int l, int r, int o, double

lm)

13int mid = (l + r) >> 1;14

if(lm > large[o << 1

]) 17

else20}

2122

void change(int p, double v, int l, int r, int

o) 28

int mid = (l + r) >> 1;29

if(p <=mid)

32else

35 large[o] = std::max(large[o << 1], large[o << 1 | 1

]);36 sum[o] = sum[o << 1] + ask(mid + 1, r, o << 1 | 1, large[o << 1

]);37

return;38

}3940int

main()

4950

return0;

51 }

ac**

洛谷 P4198 樓房重建

區間最大可修改上公升 線段樹做法,可以分塊亂搞 這道題只是詢問1到n區間,其實可以改成任意區間的最大上公升。首先注意題目是連線,因此不是高度上公升是斜率上公升 y x 但在之後的說明中都會說斜率為高度,大家把他想象成在樓底向上仰望看到多少棟樓。然後造樹,維護h,區間內最大的高度維護 s,區間內的最大...

洛谷P4198 樓房重建 分塊

小a的樓房外有一大片施工工地,工地上有n棟待建的樓房。每天,這片工地上的房子拆了又建 建了又拆。他經常無聊地看著窗外發呆,數自己能夠看到多少棟房子。為了簡化問題,我們考慮這些事件發生在乙個二維平面上。小a在平面上 0,0 點的位置,第i棟樓房可以用一條連線 i,0 和 i,hi 的線段表示,其中hi...

洛谷 P4198 樓房重建 題解

題面 首先你要知道題問的是什麼 使用一種資料結構,動態地維護以1為起點地最長上公升子串行 把樓房的高度轉化成斜率地序列 的長度 怎麼做?線段樹!初始化 對於每乙個葉子節點,從這段區間頭可以看到的樓房數量一定為1,區間斜率最大值一定為該點的斜率 在合併時 1.我們可以先查詢右區間的左區間的最大值,如果...