2957: 樓房重建
time limit: 10 sec memory limit: 256 mb
submit: 2289 solved: 1081
[submit][status][discuss]
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
output
m行,第i行乙個整數表示第i天過後小a能看到的樓房有多少棟
sample input
3 42 4
3 61 1000000000
1 1sample output
資料約定
對於所有的資料1<=xi<=n,1<=yi<=10^9
n,m<=100000
hint
source
中國國家隊清華集訓 2012-2013 第一天
[submit][status][discuss]
思路:看懂這道題還真是難啊(可能是我太笨了吧),本題用到線段樹。
在更新資料時,一直更新到頭(即l==r時),將該點更新後,回溯過程中,先記錄左右子區間的斜率最大值,再判斷如果左子區間的斜率大於等於右子區間的斜率,那麼右子區間的樓房一定看不見,該區間能看見多少樓房數就等於左子區間的樓房數,否則,就需要以左子區間的最大斜率在右子區間中尋找能看見的樓房數。以此尋找下去,返回到根節點是,就是能看到的樓房數目。
#include
#include
#include
#include
using
namespace
std;
#define n 100009
struct node
tree[n*4];
void build(int num,int l,int r)
int up(int num,double kk)
void update(int num,int x,double kk)
if(x<=mid) update(num<<1,x,kk);
else update(num<<1|1,x,kk);
tree[num].k=max(tree[num<<1].k,tree[num<<1|1].k);//記錄最大的斜率
if(tree[num<<1].k1|1].k)//更新後,左子區間的最大斜率小於右子區間的最大斜率
tree[num].inq=tree[num<<1].inq+up(num<<1|1,tree[num<<1].k);
else
//否則,就不需要在右子區間中查詢
tree[num].inq=tree[num<<1].inq;
}int main()
return
0;}
線段樹 思維題 樓房重建
小a的樓房外有一大片施工工地,工地上有n棟待建的樓房。每天,這片工地上的房子拆了又建 建了又拆。他經常無聊地看著窗外發呆,數自己能夠看到多少棟房子。為了簡化問題,我們考慮這些事件發生在乙個二維平面上。小a在平面上 0,0 點的位置,第i棟樓房可以用一條連線 i,0 和 i,hi 的線段表示,其中hi...
bzoj2957 線段樹 樓房重建
description 小a的樓房外有一大片施工工地,工地上有n棟待建的樓房。每天,這片工地上的房子拆了又建 建了又拆。他經常無聊地看著窗外發呆,數自己能夠看到多少棟房子。為了簡化問題,我們考慮這些事件發生在乙個二維平面上。小a在平面上 0,0 點的位置,第i棟樓房可以用一條連線 i,0 和 i,h...
BZOJ2957 樓房重建(線段樹)
這裡放傳送門 可以發現如果一段樓房能被看見,那麼它們跟原點的連線的斜率都是單調遞增的。於是這就變成了乙個維護上公升序列的題。這裡的上公升序列不是最長上公升子串行那樣的東西,而是相當於貪心地選擇,選中的子串行中的每乙個元素它前面都不能存在大於等於它的元素。比如說,有乙個斜率序列是1,2,4,3,4,如...