BZOJ2957樓房重建

2022-05-16 11:06:01 字數 1238 閱讀 1572

傳送門 

蒟蒻渣渣禹看到這個題時十分不想寫線段樹emmmm

於是乎。。。。分塊!!!

分塊。思路就是:如果乙個樓房能被看見,當且僅當它的房頂到(0,0)連線的斜率 比前面的都大。我們暴力維護每個塊內斜率的最長上公升序列,然後查詢的時候二分找到塊內第乙個能看到的,那麼它之後的所有最長上公升序列裡的元素就都能被看到,再去搜下乙個塊就好了。

下面我來講下具體過程,我們要求的個數,就是斜率最長上公升子串行,大家思考一下。。。顯然成立。

我們設a,b以及他們的高度為h[a],h[b],如果a不會被b擋住,那麼我們可以推出這樣乙個式子:h[a]/a >= h[b]/b,交叉相乘之後可得:h[a]b >= h[b]a。

對於原點的話我們只要判斷h[a]是否大於0就行了。

修改:然後我們暴力更新塊內元素資訊,每次清零,重新維護塊內最長上公升序列長度。

查詢:我們設last為上乙個滿足條件的塊的末尾節點,那麼從第一塊開始到最後一塊,在塊內進行二分查詢出與last相比剛滿足條件的點,那麼,從這個點一直到末尾均為合法序列,那麼ans=這段序列的長度qwq,然後更新last為本塊的末尾。

我們在暴力搞定每個塊的遞增數列,把這些斜率從小到大塞到乙個棧裡邊(時間複雜度o(n/b),b為塊的大小)。

然後查詢時從頭開始,在每個塊對應的棧中二分查詢第乙個斜率比前乙個大的位置,這個位置和棧裡面後邊的位置都能被看到(時間複雜度o(blog(n/b)))。

總時間複雜度為o(n(n/b + blog(n/b)))≈o(n(n/b + blogn))。

這樣一來b=√(n/logn)/2有奇效。想知道為什麼麼?

通過我巨水無比的計算,以及一次次試錯試出的,不然會tle,除非你開o2,強烈建議用快讀。

不用o2優化**如下qwq

#include#include#include#include#define n 100005

#define ll long long

using namespace std;;

int n,m,b,h[n],p[n];

struct stack t[330];

bool check(ll a,ll b)

inline int read()

while(ch>='0'&&ch<='9')

return w;

}int main()

else l = mid + 1;

}if(q)

}printf("%d\n",ans);

}}

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