題目鏈結
題目大意:數軸上有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了,只能說考試時候資料水了。這題有兩種做法,一種...