樓房重建 (BZOJ 2957)

2021-09-22 19:58:03 字數 2328 閱讀 5112

樓房重建 (bzoj-2957)

小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 4

3 6

1 1000000000

1 1

sample output

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

思路:

如果乙個樓房能被看見的話,那麼他樓的最高點到(0,0)直線的斜率一定嚴格大於他前面所有直線的斜率,也就是hi/xi的值是遞增的。

我們去維護乙個區間中能看到多少樓,就是求[l,mid] 和[mid+1,r]兩個區間的總貢獻。很顯然如果前面的高的話,那麼一定會擋住後面的,所有乙個區間的答案至少應該等於他左兒子的答案,那麼對於右兒子我們需要用左兒子的最大值來計算他對當前區間的貢獻(注意貢獻不一定等於[mid,r]的答案,所有我麼只是計算,不能更改[mid,r]的值)

那麼如果計算呢?

分類討論: 另左兒子的最大值=v

如果區間的最大值<=v的話,這個區間就會被前乙個區間完全擋住,所有貢獻為0,直接返回。

如果當前區間左兒子的最大值<=v,你就是是說區間左兒子一定會被這個最大值完全擋住,所以左兒子貢獻一定是0,去計算右兒子的貢獻。

如果當前區間左兒子的最大值》v ,那麼我們之前使用區間左兒子的最大值去計算的區間右兒子的貢獻,現在v《區間左兒子的最大值,那麼也就是說v對於區間右兒子是沒有影響的,直接計算上區間右兒子的貢獻即可(a[rt]-a[rt<<1],注意一定不能是a[rt<<1|1],因為那是對於右兒子的答案,而不是右兒子對當前區間的答案),然後跳轉到區間的左兒子,重複以上過程  。

ac**:

#include #include #include #include #include #include #include #include #include #include #define pi 3.1415926

#define inf 0x3f3f3f3f

const int maxn=100010;

using namespace std;

double sum[maxn<<2];

int a[maxn<<2];

void pushup(int rt)

int cupid(int l,int r,double v,int rt)

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

if(sum[rt]<=v)

return 0;

if(sum[rt<<1]<=v)

return cupid(m+1,r,v,rt<<1|1);

else

return a[rt]-a[rt<<1]+cupid(l,m,v,rt<<1);

}void change(int x,double v,int l,int r,int rt)

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

if(x<=m)

change(x,v,l,m,rt<<1);

else

change(x,v,m+1,r,rt<<1|1);

a[rt]=a[rt<<1]+cupid(m+1,r,sum[rt<<1],rt<<1|1);

sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);

}int main()

return 0;

}

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