Siyuan

「Codeforces 1152E」Neko and Flashback
「Codeforces 1152E」Neko and Flashback
扫描右侧二维码阅读全文
19
2019/05

「Codeforces 1152E」Neko and Flashback

题目链接:Codeforces 1152E

现在 Neko 有一个长度为 $n$ 的数组 $a$ 和一个长度为 $n - 1$ 的排列 $p$。现在他进行如下操作:

  • 构造一个长度为 $n - 1$ 的数组 $b$,其中 $b_i = \min(a_i, a_{i +1})$。
  • 构造一个长度为 $n - 1$ 的数组 $c$,其中 $c_i = \max(a_i, a_{i +1})$。
  • 构造一个长度为 $n - 1$ 的数组 $b'$,其中 $b'_i = b_{p_i}$。
  • 构造一个长度为 $n - 1$ 的数组 $b'$,其中 $c'_i = c_{p_i}$。

然而 Neko 只记得数组 $b'$ 和 $c'$ 了,将原来的数组 $a$ 和排列 $p$ 都忘记了。他想让你帮他找到任何一个合法的数组 $a$。如果没有任何一个可能的数组,那么输出 -1

数据范围:$2 \le n \le 10 ^ 5$,$1 \le b'_i, c'_i \le 10 ^ 9$。


Solution

我们发现,对于 $b_i, c_i$ 一定有 $(a_i, a_{i + 1}) = (b_i, c_i)$ 或 $(a_i, a_{i + 1}) = (c_i, b_i)$,那么考虑 $b, c$ 的置换 $b', c'$,一定有 $(a_{p_i}, a_{p_{i + 1}}) = (b'_i, c'_i)$ 或 $(a_{p_i}, a_{p_{i + 1}}) = (c'_i, b'_i)$。

于是我们构造一张图,连无向边 $(b'_i, c'_i)$,然后在这张图上尝试找到一条欧拉路径(注意不一定是回路),就是最终的答案;否则说明无解。

时间复杂度:$\mathcal O(n \log n)$。


Code

#include <cstdio>
#include <algorithm>
#define fail return printf("-1\n"), 0

const int N = 1e5 + 5, M = 2e5 + 5;

int n, top, b[N], c[N], t[M], p[N], ans[N];
int tot, lnk[N], ter[M], nxt[M], id[M], deg[M];
bool vis[N];

int disc() {
    int tot = 0;
    for (int i = 1; i < n; i++) t[++tot] = b[i], t[++tot] = c[i];
    std::sort(t + 1, t + tot + 1);
    tot = std::unique(t + 1, t + tot + 1) - (t + 1);
    for (int i = 1; i < n; i++) {
        b[i] = std::lower_bound(t + 1, t + tot + 1, b[i]) - t;
        c[i] = std::lower_bound(t + 1, t + tot + 1, c[i]) - t;
    }
    return tot;
}
void addEdge(int u, int v, int x) {
    ter[++tot] = v, nxt[tot] = lnk[u], lnk[u] = tot, id[tot] = x;
}
void dfs(int u) {
    for (int &i = lnk[u]; i; i = nxt[i]) {
        int v = ter[i], x = id[i];
        if (vis[x]) continue;
        vis[x] = true, dfs(v);
    }
    ans[++top] = u;
}
int main() {
    scanf("%d", &n);
    for (int i = 1; i < n; i++) scanf("%d", &b[i]);
    for (int i = 1; i < n; i++) scanf("%d", &c[i]);
    for (int i = 1; i < n; i++) if (b[i] > c[i]) fail;
    int k = disc();
    for (int i = 1; i < n; i++) {
        addEdge(b[i], c[i], i);
        addEdge(c[i], b[i], i);
        deg[b[i]]++, deg[c[i]]++;
    }
    int cnt = 0;
    for (int i = 1; i <= k; i++) if (deg[i] & 1) p[++cnt] = i;
    if (cnt > 2) fail;
    dfs(cnt ? p[1] : 1);
    if (top < n) fail;
    for (int i = top; i >= 1; i--) {
        printf("%d%c", t[ans[i]], " \n"[i == 1]);
    }
    return 0;
}
最后修改:2019 年 06 月 01 日 05 : 55 PM

发表评论