樓房 洛谷1382 codevs2995

2022-04-02 19:22:53 字數 3416 閱讀 4482

地平線(x軸)上有n個矩(lou)形(fang),用三個整數h[i],l[i],r[i]來表示第i個矩形:矩形左下角為(l[i],0),右上角為(r[i],h[i])。地平線高度為0。在輪廓線長度最小的前提下,從左到右輸出輪廓線。

下圖為樣例2。

輸入格式:

第一行乙個整數n,表示矩形個數

以下n行,每行3個整數h[i],l[i],r[i]表示第i個矩形。

輸出格式:

第一行乙個整數m,表示節點個數

以下m行,每行乙個座標表示輪廓線上的節點。從左到右遍歷輪廓線並順序輸出節點。第乙個和最後乙個節點的y座標必然為0。

輸入樣例#1:

【樣例輸入1】

23 0 2

4 1 3

【樣例輸入2】

53 -3 0

2 -1 1

4 2 4

2 3 7

3 6 8

輸出樣例#1:

【樣例輸出1】

60 0

0 31 3

1 43 4

3 0【樣例輸出2】

14-3 0

-3 3

0 30 2

1 21 0

2 02 4

4 44 2

6 26 3

8 38 0

【資料範圍】

對於30%的資料,n<=100

對於另外30%的資料,n<=100000,1<=h[i],l[i],r[i]<=1000

對於100%的資料,1<=n<=100000,1<=h[i]<=10^9,-10^9<=l[i]這些都是看了學長的部落格再寫出來的,但是我覺得他寫的不夠碉,我看不懂,於是我也來寫乙個

掃瞄線+堆,我不會掃瞄線,現學的picture(poj1177),幾近崩潰,後來回到這個題上發現這裡用到的掃瞄線也不過如此。

堆,用的是stl裡的multiset,他們說這個可以自己排序,還能當堆使,很神奇

仔細想想這個題,有很多種情況

這諸多情況,真是想想就頭疼。

但是掃瞄線,再加上堆的強大援助就能解決

下面我就用十分通俗的語言講解我的思路

掃瞄線,就是每一條豎著的線,樓房左側的線叫入邊,右側的線叫出邊,掃瞄線有長度(高度)up,橫座標x和出入邊的標識k(k=1為入邊,k=2為出邊)。

struct

linel[

200020];

把所有豎邊都加入掃瞄線後,就進行排序,排序要按照從左到右的順序

如果橫座標相同,入邊在先,出邊在後

如果同為入邊,高的在先,矮的在後,防遮擋

如果同為出邊,矮的在先,高的在後,防遮擋

int

cmp(line i,line j)

通過對圖形的分析,我們發現,能夠參與答案的只有目前的最高點,

所以我們對於入邊只需要堆的最大值,其他的儘管加上

對於出邊只需要判斷一下是否是此刻的最大值,然後加加刪刪

#include#include

#include

using

namespace

std;

intn;

struct

builda[

100010

];struct

linel[

200020

];int

cnt,num;

struct

ansans[

400040

];multiset

s;intcmp(line i,line j)

intmain()

sort(l+1,l+cnt+1

,cmp);

s.insert(0);

for(int i=1;i<=cnt;i++)

}if(l[i].k==2

)

else

s.erase(s.find(l[i].up));}}

cout

for(int i=1;i<=num;i++)

}

掃瞄線+堆

線段樹,不感興趣

/*

離散化+線段樹+模擬

由於資料量太大,我們先把所有的牆壁離散化,用線段樹維護每個離散化後的橫座標的最高點,

然後模擬求出答案。

*/#include

#include

#include

#define lson l,m,now*2

#define rson m+1,r,now*2+1

#define m 200010

using

namespace

std;

int mx[m*4],tag[m*4],a[m*2],b[m*2],ans1[m*5],ans2[m*5],n,cnt=1

;struct

node

;node q[m];

intread()

while(c>='

0'&&c<='9')

return num*flag;

}void push_up(int

now)

void push_down(int

now)

void change(int x,int y,int v,int l,int r,int

now)

push_down(now);

int m=(l+r)/2

;

if(m>=x)change(x,y,v,lson);

if(y>m)change(x,y,v,rson);

push_up(now);

}int query(int x,int l,int r,int

now)

intmain()

sort(a+1,a+2*n+1);b[1]=a[1

];

for(int i=2;i<=2*n;i++)

if(a[i]!=a[i-1])b[++cnt]=a[i];

for(int i=1;i<=n;i++)

int tot=0

;

for(int i=1;i<=cnt;i++)

printf(

"%d\n

",tot*2

);

for(int i=1;i<=cnt;i++)

if(ans2[i]!=ans2[i-1

])

return0;

}

線段樹

洛谷 4198 樓房重建

傳送門 在乙個二維平面上有 n nn 棟樓房,第 i ii 棟樓房可以用以 i,0 i,0 i,0 和 i,hi i,h i i,hi 為端點的線段表示,一開始所有的 hi 0h i 0 hi 0。有 m mm 次操作,每次可以修改乙個 h ih i hi 並且在每次修改之後查詢在 0,0 0,0 ...

洛谷P4198 樓房重建

題意 給定序列,每次修改乙個值,求字首最大值的個數。解 線段樹經典應用。每個節點維護最大值和該區間字首最大值個數。發現我們不用下傳標記,只需要合併區間。需要實現乙個函式int ask l r lm 求出區間 l r 中前乙個數是lm時字首最大值個數。那麼當lm large ls 時,return a...

洛谷 P4198 樓房重建

區間最大可修改上公升 線段樹做法,可以分塊亂搞 這道題只是詢問1到n區間,其實可以改成任意區間的最大上公升。首先注意題目是連線,因此不是高度上公升是斜率上公升 y x 但在之後的說明中都會說斜率為高度,大家把他想象成在樓底向上仰望看到多少棟樓。然後造樹,維護h,區間內最大的高度維護 s,區間內的最大...