小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
線段樹,時間複雜度為nlog(n)log(n),維護 區間斜率最大值 以及 所看到的樓房的數量
能看見的樓房,斜率一定是遞增的
對於區間【 l , r 】看到的樓房個數為左區間【l ,mid 】的看到的樓房的數量 + 在滿足大於左區間的最大斜率的情況下 右區間【mid+1 , r 】看到的樓房數量
如果右區間【mid+1 , r 】的最大斜率≤左區間【l ,mid】的最大斜率,那合併後左區間看到的樓房數為 0
如果右區間【mid+1 , r 】的左區間【mid+1,mid】最大斜率≤左區間【l ,mid 】的最大斜率,那麼右區間【mid+1 , r 】的右區間【mid+1,r】最大斜率肯定有大於左區間【l,mid】的存在,我們就遞迴處理區間【mid+1,r】所看到的樓房數
否則,那麼我們就要同時計算滿足前面的斜率 區間【mid+1,mid】和【mid+1,r】的 所看到的樓房數
滿足前面斜率的條件【mid+1,r】看到的為【l,r】- 【l,mid】
滿足前面斜率的條件【l , mid】的樓房數 繼續遞迴求
若看不懂請看
大佬的部落格
c++ code:
#include usingnamespace
std;
const
int n=100005;
struct
treetree[n*4];
int cal(int now,double k,int l,intr)
void update(int now,int l,int r,int x,double
k)
int mid=(l+r)>>1
;
if(x<=mid) update(now<<1
,l,mid,x,k);
else update(now<<1|1,mid+1
,r,x,k);
tree[now].k=max(tree[now<<1].k,tree[now<<1|1
].k);
tree[now].sum=tree[now<<1].sum+cal(now<<1|1,tree[now<<1].k,mid+1
,r); }
intmain()
return0;
}
bzoj 2957 樓房重建
小a的樓房外有一大片施工工地,工地上有n棟待建的樓房。每天,這片工地上的房子拆了又建 建了又拆。他經常無聊地看著窗外發呆,數自己能夠看到多少棟房子。為了簡化問題,我們考慮這些事件發生在乙個二維平面上。小a在平面上 0,0 點的位置,第i棟樓房可以用一條連線 i,0 和 i,hi 的線段表示,其中hi...
BZOJ2957 樓房重建
description 小a的樓房外有一大片施工工地,工地上有n棟待建的樓房。每天,這片工地上的房子拆了又建 建了又拆。他經常無聊地看著窗外發呆,數自己能夠看到多少棟房子。為了簡化問題,我們考慮這些事件發生在乙個二維平面上。小a在平面上 0,0 點的位置,第i棟樓房可以用一條連線 i,0 和 i,h...
BZOJ2957 樓房重建
題意 給定m m 100000 個操作,每次將座標軸上橫座標為x 1 x n 100000 的樓的高度設為y,之後回答在 0,0 能看到幾個樓。分析 7.19考試題,當時全場基本都寫得o nm 大暴力,gzz神犇用騙分法竟然ac了,但在bzoj上tle了,只能說考試時候資料水了。這題有兩種做法,一種...