bzoj 2957 樓房重建 線段樹

2022-04-30 06:12:13 字數 1585 閱讀 4659

小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

————————————————————

這道題可以用線段樹維護 因為涉及的只有單點修改 我們考慮一下怎麼上傳資訊就可以了

記ans為只考慮當前區間的答案 mx為區間高度最大值

考慮合併兩個區間 對於左區間那肯定是沒有影響的 這個時候我們只需要考慮右區間

我們考慮右區間的左右子區間

如果左子區間的mx<=左區間的mx 那麼這個子區間貢獻為0

遞迴處理右子區間就可以了 

如果左子區間的mx>左區間的mx 那麼右子區間不受影響 直接加上答案就可以了 然後遞迴處理左子區間

這樣其實蠻好寫的23333

#include#include

#include

using

std::max;

const

int m=1e5+7

;int

read()

while(c>='

0'&&c<='9')

return ans*f;

}struct postr[4*m];

intn,m,pos;

double

val;

int calc(int x,int l,int r,double

val)

void modify(int x,int l,int

r)

int mid=(l+r)>>1

;

if(pos<=mid) modify(x<<1

,l,mid);

else modify(x<<1^1,mid+1

,r);

tr[x].mx=max(tr[x<<1].mx,tr[x<<1^1

].mx);

tr[x].ans=tr[x<<1].ans+calc(x<<1^1,mid+1,r,tr[x<<1

].mx);

}int

main()

return0;

}

view code

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...