CF1256E. Yet Another Division Into Teams 题解 单调队列优化dp
原创
©著作权归作者所有:来自51CTO博客作者wx5a330bd704750的原创作品,请联系作者获取转载授权,否则将追究法律责任
题目链接: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;
}