[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.可能有兩個端點顏色相同的情況