CF1006B Polycarp's Practice 題解
阿新 • • 發佈:2021-12-16
CF1006B Polycarp's Practice 題解
Content
給定一個長度為 \(n\) 的數列,試將其分成 \(k\) 段,使得每一段中的最大值的和最大。
資料範圍:\(1\leqslant k,n,a_i\leqslant 2000\)。
Solution
我們不難發現,最優的方案其實就是將前 \(k\) 大的數各自單獨放在一段裡面,所以我們排序得到前 \(k\) 大的數,再找到他們的位置。那麼如何記錄每一段裡面的其他數呢?我的方案是,將前 \(k-1\) 大的數作為每一段的最後一個數儲存,剩下的那個數所在的段就是沒有被前面的 \(k-1\) 個段佔的部分,這下就可以輕鬆地解決問題了。
Code
#include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <iostream> using namespace std; int a[2007], sum, n, k, ids[2007]; struct node { int val, id; bool operator < (const node& ou) const {return val > ou.val;} }a1[2007]; int main() { scanf("%d%d", &n, &k); for(int i = 1; i <= n; ++i) { scanf("%d", &a[i]); a1[i].val = a[i], a1[i].id = i; } sort(a1 + 1, a1 + n + 1); for(int i = 1; i <= k; ++i) ids[i] = a1[i].id, sum += a1[i].val; sort(ids + 1, ids + k + 1); printf("%d\n", sum); int lastans = 0; for(int i = 1; i < k; ++i) {printf("%d ", ids[i] - ids[i - 1]); lastans += ids[i] - ids[i - 1];} printf("%d", n - lastans); return 0; }