1. 程式人生 > >【BZOJ】1584: [Usaco2009 Mar]Cleaning Up 打掃衛生

【BZOJ】1584: [Usaco2009 Mar]Cleaning Up 打掃衛生

tail 快速 最壞情況 get 枚舉 過程 最優解 不同的 參考

【算法】DP+數學優化

【題意】把n個1~m的數字分成k段,每段的價值為段內不同數字個數的平方,求最小總價值。n,m,ai<=40000

【題解】

參考自:WerKeyTom_FTD

令f[i]表示把前i個數分成若幹段的最小價值。

轉移中我們定義,從i開始往前到有j個不同的數的最小位置為b[j]。

f[i]=f[b[j]-1]+j^2。

考慮最壞情況,每個數自成一段,則總價值為n。

所以當段內不同的數個數>√n時,就不可能是最優解了(此時價值>n)。

所以f[i]=f[b[j]-1]+j^2,1<=j<=√n。

快速計算的關鍵在遞推b[j]數組,首先在遞推過程中同步計算上一個等數位置last[]和桶c[]。

枚舉j:

如果last[i]>=b[j],不會新增數,不改變。

否則,b[j]++直到c[a[b[j]]]=a[b[j]],此時b[j]++得到新的b[j]。

註意若元素個數不滿√n個,出現新元素就top++。

【BZOJ】1584: [Usaco2009 Mar]Cleaning Up 打掃衛生