bzoj 2957 樓房重建

2022-05-01 04:42:10 字數 1271 閱讀 5961

小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能看到的樓房有多少棟

這道題實際上就是讓我們維護最長上公升子串行,我們可以維護一棵線段樹,每個節點儲存兩個資訊,乙個是區間最大斜率maxl,還有乙個就是區間lis長度tr.難點在於如何將兩個區間合併.我們考慮以下三種情況:

我們先記父節點左區間的maxl為v,考慮右子區間.(因為答案至少為左子區間的答案)我們再記右子區間的左右兒子的maxl分別為maxl1,maxl2.

**如下

#include #include using namespace std;

static const int maxm=1e6+10;

int tr[maxm],lft[maxm],rht[maxm];

double maxl[maxm];

int n,m;

void build(int id,int l,int r)

int calc(int id,int l,int r,double v)

void modify(int id,int pos,double v)

int l=lft[id];int r=rht[id];int mid=(l+r)>>1;

if(pos<=mid)modify(id<<1,pos,v);

else modify(id<<1|1,pos,v);

tr[id]=tr[id<<1]+calc(id<<1|1,mid+1,r,maxl[id<<1]);

maxl[id]=max(maxl[id<<1],maxl[id<<1|1]);

}int main()

return 0;

}

點我進入ac通道

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