1. 程式人生 > >[BZOJ3523][Poi2014]KLO-Bricks——全網唯一 一篇O(n)題解+bzoj最優解

[BZOJ3523][Poi2014]KLO-Bricks——全網唯一 一篇O(n)題解+bzoj最優解

Description

有n種顏色的磚塊,第i種顏色的磚塊有a[i]個,你需要把他們放成一排,使得相鄰兩個磚塊的顏色不相同,限定第一個磚塊的顏色是start,最後一個磚塊的顏色是end,請構造出一種合法的方案或判斷無解。

 

HINT

 

【資料範圍】

n,m≤1000000,1≤start,end≤n

∑ai<=1000000

Solution

全網唯一 一篇O(n)題解+bzoj最優解

 

這個題看大家都是優先佇列,然後直接貪心放置。

還有用權值線段樹來模擬堆過的%%%。

其實不用帶logn也可以過的。

 

 

大家的方法是從左往右掃過去的。

對於這種插空排序的問題,還有一種考慮方法就是每個種類每個種類來考慮。

好處是,前面放過的種類放完了,和當前第i種永遠不會產生衝突。

這就是我的大方向思路。

 

一、先不考慮端點固定的情況。

其實,不一定要先放最多的。

順序可以隨便。

假設放到完了前i種,那麼,一共有sum[i]個。

對於後面的n-i種來說,前i種的方法對後面沒有影響。

所以,肯定前i种放法中,選擇相鄰的情況最少的方案咯!

怎樣湊出這個方案?

放完了前i種,設還剩下k個相鄰位置。

1.對於第i種,肯定先插那k個位置中。這樣每次相鄰的-1,已經最優。

2.如果i種還剩下,那就從前面開始插空(不能和1中放的相鄰)。這樣相鄰的數量不增不減。已經最優。

3.如果還剩下,那沒有辦法了。為了之後好處理,我們都把這些剩下的都放在末尾。

這樣,不管你是數量較多的,還是數量較少的,

較多的,可以放在一起,由後面的再插空隔開。

較少的,就隔開之前相鄰的。

 

至於怎麼插空?

用一個最普通的連結串列就可以維護。

當然,我們每次要維護3中,開始連續的那一串的起始位置。方便下次直接訪問。

 

 

 

二、有固定點呢?

兩個端點比較麻煩。

所以我們就先放端點好了。

放的方法和上面差不多。

先放p,再放q

如果p的數量大於等於q。

那麼放q的時候,直接插空,然後無論如何留下一個放末尾。

如果p的數量小於q。

那麼放q的時候,插完空,直接往後放完即可。

(注意的是,這樣的話有一個情況,就是在最後一個和倒數第二個之間還要插一個,後面放的時候特判一下)

 

然後放剩下k-2種。

按照剛才的策略即可。注意不能放在1前面,以及最後一個後面。

 

三、一些細節

1.可能有兩個端點顏色相同的情況