若 \(2\min\limits_{i = 1}^m a_i < \max\limits_{i = 1}^n a_i\) 就无解,因为根据排列的性质必然存在 \(yxxxy\) 或两端 \(xxyy\) 的情况,并且若这个条件不满足,就可以构造一组解。
考虑最小化字典序。枚举排列和之前重合的长度,从小到大尝试加入。
如果 \(2mn + 1 < mx\) 就无解,如果 \(2mn \ge mx\) 就一定有解。
如果 \(2mn + 1 = mx\),那么要先填 \(x\),再填 \(y\)。
取字典序最小的情况即可。
code
// Problem: E - Permutation Cover
// Contest: AtCoder - AtCoder Grand Contest 046
// URL: https://atcoder.jp/contests/agc046/tasks/agc046_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))
using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;
const int maxn = 1010;
int m, a[maxn], n, b[maxn];
bool vis[maxn];
basic_string<int> ans, res;
inline void work(int x) {
mems(vis, 0);
for (int i = 1; i <= m - x; ++i) {
vis[ans[(int)ans.size() - i]] = 1;
}
basic_string<int> vc;
for (int i = 1; i <= m; ++i) {
if (!vis[i]) {
--b[i];
vc += i;
}
}
int mn = *min_element(b + 1, b + m + 1), mx = *max_element(b + 1, b + m + 1);
if (mn * 2 + 1 < mx) {
return;
} else if (mn * 2 >= mx) {
res = min(res, vc);
} else {
basic_string<int> S;
int lst = 0;
for (int i : vc) {
if (b[i] == mx) {
lst = i;
}
}
for (int i = 0; i < (int)vc.size(); ++i) {
int x = vc[i];
if (b[x] != mn || x > lst) {
S += x;
}
if (x == lst) {
for (int j = 0; j < i; ++j) {
if (b[vc[j]] == mn) {
S += vc[j];
}
}
}
}
res = min(res, S);
}
}
void solve() {
scanf("%d", &m);
for (int i = 1; i <= m; ++i) {
scanf("%d", &a[i]);
n += a[i];
}
int mn = *min_element(a + 1, a + m + 1), mx = *max_element(a + 1, a + m + 1);
if (mn * 2 < mx) {
puts("-1");
return;
}
while ((int)ans.size() < n) {
res = basic_string<int>(1, 1e9);
for (int i = ans.size() ? 1 : m; i <= min(n - (int)ans.size(), m); ++i) {
for (int j = 1; j <= m; ++j) {
b[j] = a[j];
}
work(i);
}
for (int i : res) {
--a[i];
}
ans += res;
}
for (int x : ans) {
printf("%d ", x);
}
}
int main() {
int T = 1;
// scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}
- Permutation AtCoder Contest Grand Coverpermutation atcoder contest grand authentic atcoder contest grand negative atcoder contest grand atcoder contest radius grand atcoder contest grand 022 atcoder contest grand 001 atcoder contest descent grand histogram atcoder contest grand atcoder contest grand 019 atcoder contest grand 017