小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
正解:線段樹。
其實去年的聯賽模擬就考過這題了,比較無聊所以重做一遍。。
這是乙個線段樹的板子題,首先我們考慮維護乙個區間的可見點數$sum$,那麼答案就是$sum[rt]$。
如何在單點修改以後維護$sum$?我們考慮乙個區間的$sum$,首先左兒子的$sum$肯定是直接加上的。
同時記$max1$為左兒子的斜率最大值,我們可以遞迴右兒子來找右兒子對這個區間的貢獻。
$max2$為右兒子的左兒子的斜率最大值,如果$max2如果$max2>max1$,我們可以發現,右兒子的右兒子的貢獻就是右兒子的右兒子在右兒子這個區間的貢獻,也就是$sum[rs]-sum[ls[rs]]$,那麼直接遞迴右兒子的左兒子計算即可。
到葉子結點的時候直接判斷斜率大小關係就行了。
1 #include 2#define il inline
3#define rg register
4#define ll long long
5#define n (200010)
6#define ls (x<<1)
7#define rs (x<<1|1)
8#define eps (1e-10)910
using
namespace
std;
1112
int sum[n<<2
],n,m;
13double mx[n<<2
],k;
1415 il int
gi()
2223 il int calc(rg int x,rg int l,rg int r,rg double
k)28
29 il void update(rg int x,rg int l,rg int r,rg int p,rg double
k) rg int mid=(l+r)>>1
;31 p<=mid ? update(ls,l,mid,p,k) : update(rs,mid+1
,r,p,k);
32 sum[x]=sum[ls]+calc(rs,mid+1,r,mx[ls]),mx[x]=max(mx[ls],mx[rs]); return;33
}3435int
main()
45return0;
46 }
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了,只能說考試時候資料水了。這題有兩種做法,一種...