2957 樓房重建

2021-07-29 23:21:46 字數 1635 閱讀 7236

題目鏈結

題目大意:數軸上有n座樓,初始高度為0,每次可以改變某棟樓的高度,求每次改變高度之後從原點可以看到幾棟樓

題解:記每棟樓樓頂與原點連線的斜率,那麼一棟樓可見當且僅當前面所有樓的斜率都小於這棟樓

分塊:塊內維護特殊的lis,4 1 2 3 5 那麼維護的序列就是4 5

塊內暴力修改,查詢的時候從下一塊找到比這一塊max大的即可

線段樹做法:結點維護ans和mx,ans表示這個區間的答案,mx表示這個區間的最大斜率。

合併區間:對於節點x,ls的答案可以完全加入x的答案,接下來考慮rs

記ls最大值為m

若rs最大值小於等於

m,則rs沒有貢獻

若大於m

,把rs分成左右區間處理

若rs左區間mx小於等於

m,則遞迴處理rs右區間

若rs左區間mx大於

m ,則遞迴處理rs左區間,同時加上rs右區間的答案

右子區間的答案要用右區間答案-左子區間答案,不能直接呼叫右子區間本身答案,因為其本身答案沒有考慮左子區間的約束。

我的收穫:強強強

分塊

#include 

#include

#include

#include

#include

using

namespace

std;

#define m 100100

#define eps 1e-10

int n,m,blo,num,pos[m];

double a[m];

struct block

int cal(double &x)

}b[120];

void work()

}void init()

int main()

線段樹

#include 

#include

#include

#include

#include

using

namespace

std;

#define m 100005

#define ls x<<1

#define rs x<<1|1

#define lson l,m,x<<1

#define rson m+1,r,x<<1|1

#define root 1,n,1

int n,m,ans[m<<2],tl[m<<2],tr[m<<2];

double mx[m<<2];

int cal(double k,int x)

void pushup(int x)

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

void updata(int p,double k,int x)

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

if(p<=m) updata(p,k,ls);

else updata(p,k,rs);

pushup(x);

}void work()

}void init()

int main()

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