time limit: 10 sec memory limit: 256 mb
submit: 2739 solved: 1295
[submit][status][discuss]
小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
具體的操作都在**裡。
可以看見的樓房就是乙個從左到右斜率單增的序列,所以我們考慮用線段樹合併答案。
(是不是這種需要動態維護乙個二維偏序的長度的題都可以用玄學線段樹合併???)
/*線段樹合併的題目,mh表示區間最大斜率。
ans[o]表示只考慮o這個節點的區間可以看到的樓房數(從左到右)
顯然我們合併的時候,左兒子的ans可以直接合併進來,但是右兒子
能給父節點的貢獻會<=它的ans,因為可能會有被左兒子樓房擋住的樓房。
那麼我們考慮用calc(o,h)計算出o子樹中斜率》h的節點數量。
那麼if maxheight[leftchild]<=h then 返回 calc(rightchild,h)
//因為這種情況下左子樹中斜率最大都沒有比h大的,所以直接向右子樹遞迴查詢就好了。
else 返回 calc(leftchild,h)+ans[o]-ans[leftchild]
//這種情況下左右子樹中顯然都會有貢獻,但是因為左子樹中已經有斜率》h的了,
//所以外層的修改已經對右子樹沒有作用了。
//顯然右子樹中斜率》左子樹中最大的節點數量是ans[o]-ans[leftchild]
*/#include
#define ll long long
#define maxn 100005
using
namespace
std;
double mh[maxn<<2|1
],val;
int n,m,ans[maxn<<2|1
],pos,k;
inline
intread()
int calc(int o,int l,int r,double
height)
void update(int o,int l,int
r)
int mid=l+r>>1,lc=o<<1,rc=(o<<1)|1
;
if(pos<=mid) update(lc,l,mid);
else update(rc,mid+1
,r);
mh[o]=max(mh[lc],mh[rc]);
ans[o]=ans[lc]+calc(rc,mid+1
,r,mh[lc]);
} int
main()
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了,只能說考試時候資料水了。這題有兩種做法,一種...