description
小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
對於所有的資料1<=xi<=n,1<=yi<=10^9
n,m<=100000
output
m行,第i行乙個整數表示第i天過後小a能看到的樓房有多少棟
sample input
3 42 4
3 61 1000000000
1 1sample output11
12這題是個線段樹好題
我們記錄區間所能看到的樓房數和區間斜率最大值
為什麼記錄斜率?因為斜率大的會遮住斜率小的
考慮更新?
斜率好說,\(max\)即可
看見的樓房數怎麼更新?
首先左兒子能看到多少個,當前區間就必定能看到多少個。那右邊能看到多少個呢?
暴力尋找,用左兒子的斜率最大值(後文記為「記錄斜率」)放到右兒子中看能看到多少個
當\(l\)==\(r\)時,直接看斜率的大小關係
如果暴力尋找的區間,其左兒子的斜率最大值小於記錄斜率,那麼左兒子就啥都看不見,那我們就只關注右兒子
如果左兒子的斜率最大值大於記錄斜率,那麼我們就去暴力查詢左兒子。右兒子也要查詢嗎?不,因為右兒子一定會被左兒子的斜率最大值所遮擋,所以右兒子所能看到的個數即為\(tree[p]-tree[ls]\)
(ps:有點繞口,讀者們可以邊看**,邊理解)
#include#include#include#include#include#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline int read()
inline void print(int x)
const int n=1e5;
struct segment
void change(int p,int l,int r,int x,double y)
int mid=(l+r)>>1;
if (x<=mid) change(ls,l,mid,x,y);
if (x>mid) change(rs,mid+1,r,x,y);
k[p]=max(k[ls],k[rs]);//斜率的更新
tree[p]=tree[ls]+query(rs,mid+1,r,k[ls]);//將左兒子的斜率最大值放到右兒子中去暴力查詢
}}tree;
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了,只能說考試時候資料水了。這題有兩種做法,一種...