BZOJ2957 樓房重建

2022-05-19 19:57:46 字數 1294 閱讀 6916

給出乙個平面直角座標系,有乙個人站在(0,0)處,x軸的取值範圍為1<=x<=n

有m個操作,每個操作輸入x,y,表示在(x,0)處建一座樓,高y,如果(x,0)處本來沒有樓則看作新建,否則看作改造

對於一座樓房,它能被看到當且僅當它的最高點與(0,0)的連線沒有與其他樓有交點

求出每次操作後,這個人能看到的樓房數

線段樹好題

對於乙個樓房被看到,可以看作它與(0,0)的連線的斜率比前面所有的斜率都大

那麼我們可以把每次操作都當成單點修改,然後求整段區間從第乙個樓房開始斜率遞增所得到的樓房數

設mx為每個區間中最大的斜率,c為每個區間從左端點開始能看到的樓房數

顯然我們需要在修改的時候維護線段樹

對於一段區間,顯然左子區間的c值的貢獻一定全部在整段區間的c值中,所以我們只要對右子區間進行處理

如果當前左子區間的最大值》=右子區間的最大值,那麼右子區間對整段區間是沒有貢獻的

不然則在右子區間中找出以第乙個大於左子區間的最大值的樓房,然後貢獻為從這個樓房往後得到的樓房數(包括這個樓房)

就這樣,注意一下精度就可以了

#include#include

#include

#include

#include

#define eps 1e-10

using

namespace

std;

struct

trnode

tr[210000];int

trlen;

void bt(int l,intr)}

intans;

void findd(int now,double

d)

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

if(tr[lc].mx<=d) findd(rc,d);

else ans+=tr[now].c-tr[lc].c,findd(lc,d);

}void follow(int

now)

}void change(int now,int x,double

d)

int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2

;

if(x<=mid) change(lc,x,d);

else

change(rc,x,d);

follow(now);

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