// Gemimi 3 Pro preview #include #include #include #include using namespace std; // トポロジカルソートを用いて値を構築する関数 // mode == 0: a1 < a2 > a3 < a4 ... (谷, 山, 谷...) // mode == 1: a1 > a2 < a3 > a4 ... (山, 谷, 山...) bool solve(int N, int M, const vector& A, bool mode, vector& result_vals) { vector> adj(M + 1); vector in_degree(M + 1, 0); // 不等式制約をグラフの辺に変換 for (int i = 0; i < N - 1; ++i) { int u = A[i]; int v = A[i+1]; int from, to; if (mode == 0) { // パターン: 低, 高, 低, 高... // i=0 (偶数): 低 -> 高 なので u < v (辺 u -> v) // i=1 (奇数): 高 -> 低 なので u > v (辺 v -> u) if (i % 2 == 0) { from = u; to = v; } else { from = v; to = u; } } else { // パターン: 高, 低, 高, 低... // i=0 (偶数): 高 -> 低 なので u > v (辺 v -> u) // i=1 (奇数): 低 -> 高 なので u < v (辺 u -> v) if (i % 2 == 0) { from = v; to = u; } else { from = u; to = v; } } adj[from].push_back(to); in_degree[to]++; } // Kahnのアルゴリズムによるトポロジカルソート queue q; for (int i = 1; i <= M; ++i) { if (in_degree[i] == 0) { q.push(i); } } vector topo_order; topo_order.reserve(M); while (!q.empty()) { int u = q.front(); q.pop(); topo_order.push_back(u); for (int v : adj[u]) { in_degree[v]--; if (in_degree[v] == 0) { q.push(v); } } } // 閉路がある場合は全てのノードを訪問できない if (topo_order.size() < M) return false; // トポロジカル順序に従って値を割り当て (小さい順に 1, 2, ..., M) result_vals.assign(M + 1, 0); for (int i = 0; i < M; ++i) { // topo_order[i] は i+1 番目に小さい値を持つべき変数 result_vals[topo_order[i]] = i + 1; } return true; } int main() { // 高速化 ios_base::sync_with_stdio(false); cin.tie(NULL); int N, M; if (!(cin >> N >> M)) return 0; vector A(N); for (int i = 0; i < N; ++i) { cin >> A[i]; } // 門松列の定義「3つの要素は全て異なる」ための事前チェック // 隣り合う要素が同じだと、x_a = x_b となり条件を満たせない for (int i = 0; i < N - 1; ++i) { if (A[i] == A[i+1]) { cout << "No" << endl; return 0; } } // 1つ飛ばしの要素が同じだと、(x, y, x) となり条件を満たせない for (int i = 0; i < N - 2; ++i) { if (A[i] == A[i+2]) { cout << "No" << endl; return 0; } } vector res; // パターンA (谷・山・谷...) を試す if (solve(N, M, A, 0, res)) { cout << "Yes" << endl; for (int i = 1; i <= M; ++i) { cout << res[i] << (i == M ? "" : " "); } cout << endl; } // パターンB (山・谷・山...) を試す else if (solve(N, M, A, 1, res)) { cout << "Yes" << endl; for (int i = 1; i <= M; ++i) { cout << res[i] << (i == M ? "" : " "); } cout << endl; } // どちらも不可能 else { cout << "No" << endl; } return 0; }