BZOJ2957 樓房重建

2022-05-16 02:49:58 字數 1084 閱讀 1512

平面上有\(n\)個位置\(1\dots n\),第\(i\)個位置有乙個高為\(h_i\)的樓房;所有\(h\)初始值為\(0\)。每次修改乙個\(h_i\),求修改後從\((0,0)\)點可以看到多少樓房。\(n,m\leq10^5\)。

線段樹。

首先可以發現某個樓房能夠被看到當且僅當它的頂點斜率》所有前面的樓房頂點的斜率。

只記錄斜率,把「比前面所有數都大的數」稱為「優數」,那麼答案即為「優數」的個數

那麼線段樹每個節點維護最大值\(max\)和區內「優數」的個數\(ans\)。

先考慮查詢。我們把查詢寫成\(q(o, x)​\)表示查詢\([l_o,r_o]​\)區間(即結點\(o​\)代表的區間)內比\(x​\)大的「優數」的個數。

如果\(x\)大於等於\(max_\),那麼\(q(o,x)=q(rson, x)\)。顯然。

否則,\(q(o,x)=ans_o - (ans_-q(lson, x))\),即總「優數」個數減去左子區間裡小於等於x的「優數」個數。

再考慮如何維護資訊。\(max\)容易維護。\(ans_o=ans_+q(rson, max_)\)即可。

最終的答案就是\(q(root, 0)\)。

#include #include const int n = 100050;

typedef long long ll;

struct frac

bool operator<(const frac &f) const

}maxv[n * 4];

int lenv[n * 4], y[n];

int query(int o, int l, int r, frac x)

void upd(int o, int l, int r) else

}void modify(int o, int l, int r, int x, int y)

upd(o, l, r);

}void build(int o, int l, int r)

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