题目链接:​​https://codeforces.com/contest/1256/problem/E​

将 \(n\) 个数分成若干队,每一队至少包含 \(3\)

解题思路:

就是比较简单的单调队列优化dp,主要是下面这个公式:

​f[i] = min(f[j] - a[j+1]) + a[i]​

但是因为还有一些额外数据要输出所以再加一些操作这道题目就解决了。

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5;

int n, p[maxn], team[maxn], sz[maxn], pres[maxn];
long long f[maxn];
deque<int> que;

struct Node {
int a, p;
} a[maxn];

bool cmp(Node a, Node b) {
return a.a < b.a;
}

// f[i] = min(f[j] - a[j+1]) + a[i]

long long cal(int p) {
return f[p] - a[p+1].a;
}

int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i].a;
a[i].p = i;
}
sort(a+1, a+1+n, cmp);
for (int i = 3; i <= n; i++) {
int pre = i - 3;
if (pre != 1 && pre != 2) {
while (!que.empty() && cal(que.back()) >= cal(pre)) que.pop_back();
que.push_back(pre);
}
pres[i] = que.front();
f[i] = cal(que.front()) + a[i].a;
sz[i] = sz[que.front()] + 1;
}
for (int i = n; i; i = pres[i]) {
for (int j = pres[i]+1; j <= i; j++)
team[a[j].p] = sz[i];
}
cout << f[n] << " " << sz[n] << endl;
for (int i = 1; i <= n; i++) cout << team[i] << " ";
return 0;
}