AtCoder题解——Beginner Contest 178——F - Contrast

题目相关

题目链接

AtCoder Beginner Contest 178 F 题,https://atcoder.jp/contests/abc178/tasks/abc178_f

Problem Statement

Given are two sequences A and B, both of length N. A and B are each sorted in the ascending order. Check if it is possible to reorder the terms of B so that for each i (1 ≤ i ≤ N) Ai≠Bi holds, and if it is possible, output any of the reorderings that achieve it.

Input

Input is given from Standard Input in the following format:

N
A1 A2 ⋯ AN
B1 B2 ⋯ BN

Output

If there exist no reorderings that satisfy the condition, print No.

If there exists a reordering that satisfies the condition, print Yes on the first line. After that, print a reordering of B on the second line, separating terms with a whitespace.

If there are multiple reorderings that satisfy the condition, you can print any of them.

Samples1

Sample Input 1

6
1 1 1 2 2 3
1 1 1 2 2 3

Sample Output 1

Yes
2 2 3 1 1 1

Samples2

Sample Input 2

3
1 1 2
1 1 3

Sample Output 2

No

Samples3

Sample Input 3

4
1 1 2 3
1 2 3 3

Sample Output 3

Yes
3 3 1 2

Constraints

  • 1 ≤ N ≤ 2×10^5
  • 1 ≤ Ai, Bi ≤ N
  • A and B are each sorted in the ascending order.
  • All values in input are integers.

题解报告

题目翻译

给定两个升序序列 A 和 B,长度都是 N。请检查是否存在这样的可能性,将序列 B 重新排列,排列好的新序列满足:对于每一个 i (1 ≤ i ≤ N),而 Ai≠Bi。如果可能,请输出重新排列的最长序列 B,如果有多种可能,只需要输出其中的一种。

题目分析

题目要求我们将序列 B 重排,因此最简单的方法就是将序列 B 倒序排列。为什么倒序呢?很简单啊,因为 STL 中的 algorithm 中提供了倒序函数(reverse)。

这样序列 A 为升序,序列 B 为降序。那么在序列 A 和 B 之间可能存在一段 [l, r] 区间,使得 A_{j}=B_{j}=c \ where\ {l \leq j \leq r}。这样,[l, r] 这个区间序列 A 和 B 的数据是相同的。我们将序列 B 的 [l, r] 区间的数据和其他区间数值不为 c (a_{i}\neq c \ and \ b_{i}\neq c \ and \ l\leqslant r)的尽可能多的数据进行对换。等对换完成,如果 l\leqslant r,说明长度不够,无解。否则打印出数列 B。

样例数据分析

样例 1

根据样例数据,我们知道序列 A 为 {1, 1, 1, 2, 2, 3},序列 B 为 {1, 1, 1, 2, 2, 3}。这样序列 B 变为 {3, 2, 2, 1, 1, 1}。

遍历序列 A 和 B,没有重合的数据。因此最终结果就是新的序列 B,也就是 {3, 2, 2, 1, 1, 1}。

样例 2

根据样例数据,我们知道序列 A 为 {1, 1, 2},序列 B 为 {1, 1, 3}。这样序列 B 变为 {3, 1, 1}。

遍历数列 A 和 B,重合的位置为 [1, 1],也就是 l=1,r=1,并记录下这个重复的数据 c=1。下面我们再次遍历数列 A 和 B。

第一个数据 a[0]=1,b[0]=3。由于 a[0]==c==1,因此无法交换位置。如果我们交换 b[0] 和 b[1],因为 b[1]=1,交换后和 a[0] 的数值一样,就不符合题意。

第二个数据 a[1]=1,b[1]=1。由于 a[1]==b[1]==c==1,因此无法交换位置。

第三个数据 a[1]=2,b[1]=1。由于 b[1]==c==1,因此无法交换位置。

遍历序列 A 和 B 后,发现 l=1,r=1,也就是 l\leqslant r,说明没法交换。因此输出 No。

样例 3

根据样例数据,我们知道序列 A 为 {1, 1, 2, 3},序列 B 为 {1, 2, 3, 3}。这样序列 B 变为 {3, 3, 2, 1}。

遍历数列 A 和 B,重合的位置为 [2, 2],也就是 l=2,r=2,并记录下这个重复的数据 c=2。下面我们再次遍历数列 A 和 B。

第一个数据 a[0]=1,b[0]=3。由于 a[0]!=c 同时 b[0]!=c 同时 l\leqslant r(说明有数据可以交换),因此我们将 b[0] 和 b[2] 进行交换,交换后的序列 B 变为 {2, 3, 3, 1},l 变成 3。

第二个数据 a[1]=1,b[1]=3。由于 a[0]!=c 同时 b[0]!=c 当时 l>r(说明没有数据可以交换)。

第三个数据 a[2]=2,b[2]=3。由于 a[0]!=c 同时 b[0]!=c 当时 l>r(说明没有数据可以交换)。

第四个数据 a[3]=3,b[3]=1。由于 a[0]!=c 同时 b[0]!=c 当时 l>r(说明没有数据可以交换)。

遍历结束后,l>r。说明新的序列 B {2, 3, 3, 1} 就是我们要找的序列。

AC 参考代码

//https://atcoder.jp/contests/abc178/tasks/abc178_f
#include <bits/stdc++.h>

using namespace std;

const int MAXN=2e5+4;
long long a[MAXN];
long long b[MAXN];

int main() {
    int n;
    cin>>n;
    for (int i=0; i<n; i++) {
        cin>>a[i];
    }
    for (int i=0; i<n; i++) {
        cin>>b[i];
    }

    reverse(b, b+n);

#if 0
    cout<<"\n";
    for (int i=0; i<n; i++) {
        cout<<a[i]<<" ";
    }
    cout<<"\n";
    for (int i=0; i<n; i++) {
        cout<<b[i]<<" ";
    }
    cout<<"\n";
#endif

    //寻找重合的区间
    int c=-1;
    int l=n;
    int r=-1;
    for (int i=0; i<n; i++) {
        if (-1==c && a[i]==b[i]) {
            //第一次出现相等
            c=a[i];
            l=i;
            r=i;
        } else if (-1!=c && a[i]==b[i]) {
            //最后一次出现相等
            r=i;
        }
    }
    //cout<<l<<" "<<r<<"\n";

    //交换数据
    for (int i=0; i<n; i++) {
        if (c!=a[i] && c!=b[i] && l<=r) {
            swap(b[i], b[l]);
            l++;
        }
    }

    if (l<=r) {
        cout<<"No\n";
    } else {
        cout<<"Yes\n";
        for (int i=0; i<n; i++) {
            cout<<b[i]<<" ";
        }
    }

    return 0;
}

细节

第一次出现 a[i]==b[i] 的时候,要将 l 和 r 都记录下来。这里掉坑了。考虑测试数据 2。

猜你喜欢

转载自blog.csdn.net/justidle/article/details/108604007
今日推荐