BZOJ2957 樓房重建 線段樹

2022-09-14 16:18:17 字數 1965 閱讀 2592

小a的樓房外有一大片施工工地,工地上有n棟待建的樓房。每天,這片工地上的房子拆了又建、建了又拆。他經常無聊地看著窗外發呆,數自己能夠看到多少棟房子。

為了簡化問題,我們考慮這些事件發生在乙個二維平面上。小a在平面上(0,0)點的位置,第i棟樓房可以用一條連線(i,0)和(i,hi)的線段表示,其中hi為第i棟樓房的高度。如果這棟樓房上任何乙個高度大於0的點與(0,0)的連線沒有與之前的線段相交,那麼這棟樓房就被認為是可見的。

施工隊的建造總共進行了m天。初始時,所有樓房都還沒有開始建造,它們的高度均為0。在第i天,建築隊將會將橫座標為xi的房屋的高度變為yi(高度可以比原來大---修建,也可以比原來小---拆除,甚至可以保持不變---建築隊這天什麼事也沒做)。請你幫小a數數每天在建築隊完工之後,他能看到多少棟樓房?

第一行兩個正整數n,m

接下來m行,每行兩個正整數xi,yi

m行,第i行乙個整數表示第i天過後小a能看到的樓房有多少棟

3 42 4

3 61 1000000000

1 1111

2資料約定

對於所有的資料1<=xi<=n,1<=yi<=10^9

n,m<=100000

搞了一上午計算幾何抄了波板子被噁心的不行然後心態**

然後我就頹了一下午

乙個挺神的線段樹的題……

很容易考慮到我們可以維護斜率來統計答案

那麼我們對於一段區間,維護兩個資訊max和sum

分別代表區間內最大斜率和如果只考慮這個區間的話能看到幾個樓房

對於乙個區間[l,r],若[l,mid]的最大值大於等於[mid+1,r]的最大值,很顯然右邊的區間的貢獻是不考慮的(因為全被左邊擋住了233)

所以每次合併當前區間資訊segt[now]的時候,segt[now].max我們直接計算,segt[now].sum=左兒子的sum+計算一下右兒子能做出的貢獻

怎麼計算貢獻呢,我們可以遞迴處理右兒子的區間。設左兒子的最大值為maxn,當前遞迴處理到右兒子的區間segt[k]

1、若segt[k].max≤maxn,貢獻為0

2、若segt[k*2].max≤maxn,那麼segt[k*2+1]肯定有大於maxn的存在,我們就遞迴處理segt[k*2+1]

3、若segt[k*2].max>maxn,那麼我們就要同時計算segt[k*2]和segt[k*2+1]的貢獻。

對於segt[k*2],繼續遞迴處理。然後再加上segt[k*2+1]的貢獻

(因為此時影響右段的不是maxn,而是左段的最大值)

不過對於segt[k*2+1]的貢獻,不能直接加,要加上當前段的貢獻-左段的貢獻。

因為當前段的貢獻≠左段+右段的貢獻(van了我寫題的時候為什麼突然sb了)

複雜度nlog²n

1 #include2 #include3

using

namespace

std;45

struct nodesegt[400009];6

intn,m,x,k;78

int calc(int now,double maxn,int l,intr)9

1617

void update(int now,int l,int r,int x,double

k)18

25int mid=(l+r)>>1;26

if (x<=mid) update(now<<1

,l,mid,x,k);

27else update(now<<1|1,mid+1

,r,x,k);

28 segt[now].max=max(segt[now<<1].max,segt[now<<1|1

].max);

29 segt[now].sum=segt[now<<1].sum+calc(now<<1|1,segt[now<<1].max,mid+1

,r);30}

3132

intmain()

3341 }

BZOJ2957 樓房重建(線段樹)

這裡放傳送門 可以發現如果一段樓房能被看見,那麼它們跟原點的連線的斜率都是單調遞增的。於是這就變成了乙個維護上公升序列的題。這裡的上公升序列不是最長上公升子串行那樣的東西,而是相當於貪心地選擇,選中的子串行中的每乙個元素它前面都不能存在大於等於它的元素。比如說,有乙個斜率序列是1,2,4,3,4,如...

BZOJ2957 樓房重建 線段樹

題目 time limit 10 sec memory limit 256 mb submit 2259 solved 1069 submit status discuss 小a的樓房外有一大片施工工地,工地上有n棟待建的樓房。每天,這片工地上的房子拆了又建 建了又拆。他經常無聊地看著窗外發呆,數自...

bzoj2957樓房重建 線段樹

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