BZOJ2957 樓房重建

2022-08-19 22:45:19 字數 1800 閱讀 8902

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

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

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

\[n,m<=100000

\]先轉換問題,由於小a站在原點,那麼一幢房子能被看到的條件就是其斜率k嚴格大於之前的所有的房子的斜率, 那麼問題就變成了求一段區間內值嚴格大於之前的所有點的點的數目。

求一段區間的值, 直接採用線段樹,考慮兩個區間如何合併。在只考慮當前區間時,首先其左區間的答案一定要被統計下來。 考慮加上左端點的限制之後如何計算。 如果當前左區間的左區間的最大值大於左區間的最大值, 那麼先計算左區間的值,然後直接利用左區間計算右區間的值, 這樣就轉變為左區間對右區間可用限制。

如果右左區間的最大值比左區間要小, 那麼直接計算以當前限制繼續計算右端點即可。左區間算是廢了。

(以下區間均指右兒子之所屬)

考慮如何用已知條件計算出右區間的值。 因為當前區間的右區間是最新的值, 我們直接用右端點的答案減去右左區間的答案就可以。因為在更新當前區間時, 其值都是最新的,而這樣算是為了解決右區間要考慮氘左區間的限制。

insp: 咕咕咕

#include #include #include #include #define rep(i, a, b) for(int i = (a), i##_end_ = (b); i <= i##_end_; ++i)

#define drep(i, a, b) for(int i = (a), i##_end_ = (b); i >= i##_end_; --i)

#define clar(a, b) memset(a, (b), sizeof(a))

int read()

void write(int x)

const int maxn = (int)1e6;

int n;

namespace sgmt_tree

void modify(int rt, int l, int r, int pos, double val)

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

if(pos <= mid) modify(ls, pos, val); else modify(rs, pos, val);

max[rt] = std :: max(max[lc(rt)], max[rc(rt)]);

tree[rt] = tree[lc(rt)] + calclim(rc(rt), mid + 1, r, max[lc(rt)]); }}

void solve()

}int main()

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了,只能說考試時候資料水了。這題有兩種做法,一種...