bzoj2957 線段樹 樓房重建

2021-08-13 22:54:36 字數 1973 閱讀 4998

description

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

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

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

input

第一行兩個正整數n,m   接下來m行,每行兩個正整數xi,yi

output

m行,第i行乙個整數表示第i天過後小a能看到的樓房有多少棟

sample input

3 4

2 43 6

1 1000000000

1 1

sample output

111

2

hint

資料約定

對於所有的資料1<=xi<=n,1<=yi<=10^9

n,m<=100000

題解

首先題面描述錯了。。是每棟樓最高點與(0,0)的連線不過其他點即可。

這個連線可以用斜率表達出來就是y/x嘛

如果第i棟樓的斜率》i+1棟,那麼i+1就是不可見的。。

回來看題,修改的話只會對這棟樓後面的產生影響。。就相當於改一次要維護後面的

那還不是線段樹嘛

線段樹每個點記錄管轄範圍內斜率最大的值mxn,和只有這段區間的可見數c

修改回來的時候,設該點左孩子為lc,右孩子為rc

左孩子的值可以直接繼承,所以tr[now].c先等於tr[lc].c

左孩子修改了,右孩子一定有影響來著。那麼我們維護右孩子

設左孩子的最大值為tmp,右孩子當前處理的段就是u

假設u.mxn<tmp的話 那麼這一段就不可能有樓了,於是直接return

u.lc.mxn>tmp,左孩子有樓,那麼右孩子可以直接繼承 為u.c-u.lc.c,然後我們遞迴找左孩子

u.lc.mxn<tmp,左孩子無樓,遞迴找右孩子

upd:

之前沒寫複雜度

但這樣的複雜度顯然是n

log⁡2n

n\log ^2n

nlog2n

的…

#include#include#include#include#includeusing namespace std;

const double eps=0.0;

struct node

tr[1111000];int trlen;

void bt(int l,int r)

void ch(int now,int p,double k)

int lc=tr[now].lc,rc=tr[now].rc;

int mid=(tr[now].l+tr[now].r)/2;i

if(p<=mid)ch(lc,p,k);

else ch(rc,p,k);

tr[now].mxn=max(tr[lc].mxn,tr[rc].mxn);

tr[now].c=tr[lc].c+get(rc,tr[lc].mxn);

}int main()

return 0;

}

樓房重建 (BZOJ 2957)

樓房重建 bzoj 2957 小a的樓房外有一大片施工工地,工地上有n棟待建的樓房。每天,這片工地上的房子拆了又建 建了又拆。他經常無聊地看著窗外發呆,數自己能夠看到多少棟房子。為了簡化問題,我們考慮這些事件發生在乙個二維平面上。小a在平面上 0,0 點的位置,第i棟樓房可以用一條連線 i,0 和 ...

BZOJ2957 樓房重建(線段樹)

這裡放傳送門 可以發現如果一段樓房能被看見,那麼它們跟原點的連線的斜率都是單調遞增的。於是這就變成了乙個維護上公升序列的題。這裡的上公升序列不是最長上公升子串行那樣的東西,而是相當於貪心地選擇,選中的子串行中的每乙個元素它前面都不能存在大於等於它的元素。比如說,有乙個斜率序列是1,2,4,3,4,如...

BZOJ2957 樓房重建 線段樹

題目 time limit 10 sec memory limit 256 mb submit 2259 solved 1069 submit status discuss 小a的樓房外有一大片施工工地,工地上有n棟待建的樓房。每天,這片工地上的房子拆了又建 建了又拆。他經常無聊地看著窗外發呆,數自...