\(n\) 为偶数显然无解。
否则我们可以构造一棵 \(n\) 个点的完全二叉树,当 \(n + 1\) 是 \(2\) 的幂时满足 \(m = 1\),否则 \(m = 0\)。
当 \(n \ge 5\) 时可以递归至 \((n - 2, m - 1)\),再挂一个叶子即可。
但是可能会出现 \(n + 1\) 不是 \(2\) 的幂,但 \(n - 1\) 是,可能会把有解判成无解。
打一个补丁,如果上面那种情况递归下去无解,当 \(n \ge 11\) 时我们可以接一棵 \(3\) 个点的满二叉树,然后再递归至 \((n - 4, m - 1)\)。
时间复杂度 \(O(n)\)。
code
// Problem: E. Inverse Genealogy
// Contest: Codeforces - Codeforces Round 657 (Div. 2)
// URL: https://codeforces.com/problemset/problem/1379/E
// Memory Limit: 512 MB
// Time Limit: 1000 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 = 100100;
int n, m, a[maxn];
int dfs(int n, int m) {
if (n <= 1 || m < 0) {
return -1;
}
if ((m == 1 && (1 << (__lg(n) + 1)) != n + 1) || (m == 0 && (1 << (__lg(n) + 1)) == n + 1)) {
for (int i = 2; i <= n; ++i) {
a[i] = (i >> 1);
}
return 1;
}
int r = dfs(n - 2, m - 1);
if (r != -1) {
a[r] = a[n - 1] = n;
return n;
}
if (n > 9) {
a[n - 3] = a[n - 2] = n - 1;
a[n - 1] = n;
r = dfs(n - 4, m - 1);
if (r == -1) {
return -1;
}
a[r] = n;
return n;
}
return -1;
}
void solve() {
scanf("%d%d", &n, &m);
if (n == 1) {
if (m == 0) {
puts("YES\n0");
} else {
puts("NO");
}
return;
}
if (n % 2 == 0 || m > (n - 3) / 2) {
puts("NO");
return;
}
if (dfs(n, m) == -1) {
puts("NO");
return;
}
puts("YES");
for (int i = 1; i <= n; ++i) {
printf("%d ", a[i]);
}
putchar('\n');
}
int main() {
int T = 1;
// scanf("%d", &T);
while (T--) {
solve();
}
return 0;
}