#include <bits/stdc++.h>   using namespace std;   const int MAXN = 2020 + 1;   int vis[MAXN], par[MAXN], orig[MAXN], match[MAXN], aux[MAXN], t, N;   vector<int> conn[MAXN];   queue<int> Q;   void addEdge(int u, int v) {     conn[u].push_back(v);     conn[v].push_back(u);   }   void init(int n) {     N = n;     t = 0;     for (int i = 0; i <= n; ++i) {       conn[i].clear();       match[i] = aux[i] = par[i] = 0;     }   }   void augment(int u, int v) {     int pv = v, nv;     do {       pv = par[v];       nv = match[pv];       match[v] = pv;       match[pv] = v;       v = nv;     } while (u != pv);   }   int lca(int v, int w) {     ++t;     while (true) {       if (v) {         if (aux[v] == t)           return v;         else           aux[v] = t;         v = orig[par[match[v]]];       }       swap(v, w);     }   }   void blossom(int v, int w, int a) {     while (orig[v] != a) {       par[v] = w;       w = match[v];       if (vis[w] == 1) Q.push(w), vis[w] = 0;       orig[v] = orig[w] = a;       v = par[w];     }   }   bool bfs(int u) {     fill(vis + 1, vis + 1 + N, -1);     iota(orig + 1, orig + N + 1, 1);     Q = queue<int>();     Q.push(u);     vis[u] = 0;     while (!Q.empty()) {       int v = Q.front();       Q.pop();       for (int x : conn[v]) {         if (vis[x] == -1) {           par[x] = v;           vis[x] = 1;           if (!match[x]) return augment(u, x), true;           Q.push(match[x]);           vis[match[x]] = 0;         } else if (vis[x] == 0 && orig[v] != orig[x]) {           int a = lca(orig[v], orig[x]);           blossom(x, v, a);           blossom(v, x, a);         }       }     }     return false;   }   int Match() {     int ans = 0;     vector<int> V(N - 1);     iota(V.begin(), V.end(), 1);     shuffle(V.begin(), V.end(), mt19937(0x94949));     for (auto x : V)       if (!match[x]) {         for (auto y : conn[x])           if (!match[y]) {             match[x] = y, match[y] = x;             ++ans;             break;           }       }     for (int i = 1; i <= N; ++i)       if (!match[i] && bfs(i)) ++ans;     return ans;   }   struct UFD {     vector<int> ufd;     UFD(int n) : ufd(n) { iota(ufd.begin(), ufd.end(), 0); }     int Find(int x) {       if (x == ufd[x]) return x;       return ufd[x] = Find(ufd[x]);     }     void Union(int a, int b) { ufd[Find(a)] = Find(b); }   };   int main() {     int N;     cin >> N;     vector<int> V(N);     for (int& x : V) cin >> x;     vector<pair<int, int>> ft;     int from = -1;     for (int i = 0; i < N; ++i) {       if (V[i] == 0) {         if (from == -1) from = i;       } else {         if (from != -1) ft.emplace_back(from, i - 1);         from = -1;       }     }     if (from != -1) ft.emplace_back(from, N - 1);     if (ft.size() == 1 && ft[0].first == 0 && ft[0].second == N - 1) {       for (int i = 0; i < N; ++i) cout << (i / 2) + 1 <<    ;       cout << endl;       return 0;     }     vector<pair<int, int>> ov, av;     for (auto [f, t] : ft) {       if (f == 0) {         for (int i = 0; i + 1 <= t; i += 2) V[i] = V[i + 1] = -1;         if (t % 2 == 0) V[t] = V[t + 1];       } else if (t == N - 1) {         for (int i = t; i - 1 >= f; i -= 2) V[i] = V[i - 1] = -1;         if ((t - f) % 2 == 0) V[f] = V[f - 1];       } else {         if ((t - f + 1) % 2 == 0)           av.emplace_back(f, t);         else           ov.emplace_back(f, t);       }     }     int K = 600;     UFD ufd(K + 1);     init(K);     vector<bool> used(K + 1);     vector<int> cooked(K + 1);     for (int i = 0; i < N - 1; ++i)       if (V[i] == V[i + 1] && V[i] > 0) used[V[i]] = 1;     vector<pair<int, int>> raw;     for (auto [f, t] : ov) {       int s = V[f - 1], e = V[t + 1];       if (ufd.Find(s) == ufd.Find(e)) {         cooked[s] = s;         used[s] = 1;         V[f] = V[f - 1];         for (int i = f + 1; i <= t; ++i) V[i] = -1;       } else         raw.emplace_back(f, t);       ufd.Union(s, e);     }     for (int i = 1; i <= K; ++i)       if (cooked[i]) cooked[ufd.Find(i)] = cooked[i];     for (int i = 1; i <= K; ++i)       if (cooked[ufd.Find(i)]) used[i] = 1;     vector<vector<int>> added(K + 1, vector<int>(K + 1, -1));     for (int i = 0; i < (int)av.size(); ++i) {       auto [f, t] = av[i];       int s = ufd.Find(V[f - 1]), e = ufd.Find(V[t + 1]);       if (used[s] || used[e]) continue;       if (added[s][e] != -1) continue;       if (s == e) continue;       added[s][e] = added[e][s] = i;       addEdge(s, e);     }     Match();     vector<int> root(K + 1);     for (int i = 1; i <= K; ++i)       if (match[i] && match[i] > i) {         int s = i, e = match[i];         auto [f, t] = av[added[s][e]];         V[f] = V[f - 1];         V[t] = V[t + 1];         used[V[f - 1]] = used[V[t + 1]] = 1;         for (int j = f + 1; j <= t - 1; ++j) V[j] = -1;       }     for (auto [f, t] : av)       if (V[f] == 0)         for (int j = f; j <= t; ++j) V[j] = -1;     vector<vector<tuple<int, int, int>>> conn(K + 1);     for (auto [f, t] : raw) {       int s = V[f - 1], e = V[t + 1];       conn[s].emplace_back(e, f, t);       conn[e].emplace_back(s, f, t);     }     function<void(int, int)> dfs = [&](int a, int p) {       for (auto [b, f, t] : conn[a])         if (b != p) {           if (V[f] == 0) {             for (int i = f; i <= t; ++i) V[i] = -1;             if (V[f - 1] == b)               V[f] = b;             else               V[t] = b;           }           dfs(b, a);         }     };     for (int i = 1; i <= K; ++i)       if (ufd.Find(i) == i) {         int p = i;         if (cooked[p])           p = cooked[p];         else           for (int i = 1; i <= K; ++i)             if (used[i] && ufd.Find(i) == p) p = i;         dfs(p, -1);       }     for (int i = 0; i < N - 1; ++i)       if (V[i] == V[i + 1] && V[i] > 0) used[V[i]] = 1;     int tp = 1;     for (int i = 0; i < N - 1; ++i)       if (V[i] == -1) {         while (tp <= K && used[tp]) ++tp;         assert(V[i + 1] == -1);         V[i] = V[i + 1] = tp;         if (tp <= K) used[tp] = 1;         ++tp;       }     for (auto x : V) cout << x <<    , assert(x > 0);     cout << endl;   }