地平線(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】輸出樣例#1:23 0 2
4 1 3
【樣例輸入2】
53 -3 0
2 -1 1
4 2 4
2 3 7
3 6 8
【樣例輸出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,區間內的最大...