{ }codelper
値の入れ替えn行の読み込みP0046

カードの入れ替え

カード n 枚が一列に並んでいて、左から 1 番、2 番、…、n 番の位置である。
一行目に n と入れ替えの回数 m が与えられ、二行目にカードに書かれた n 個の数が左から与えられる。
続く m 行には一行に位置の番号 i と j が与えられる。
与えられた順に i 番の位置のカードと j 番の位置のカードを入れ替える(i と j が同じなら何も起きない)。
すべて入れ替えたあと、カードの数を左から空白一つで区切って一行に出力せよ。

入力
1 ≤ n ≤ 1,000、1 ≤ m ≤ 1,000、1 ≤ カードの数 ≤ 1,000,000,000、1 ≤ i, j ≤ n
出力
カード n 枚の数を一行
例 1 · stdin
4 3
10 20 30 40
1 4
2 3
1 2
stdout
30 40 20 10
例 2 · stdin
3 3
3 3 8
1 2
2 2
3 1
stdout
8 3 3
main.py
入力(stdin)

実行すると、これらの行が順に input()・標準入力に渡されます(実行中に入力を求めません)。

$ 準備完了

コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。

ほかの言語では?言語別の解答を見る · 8 言語の解答

二つの値を入れ替える一行の文法がある言語とない言語に分かれます。
Python a[i], a[j] = a[j], a[i](右のタプルを先に作ってから分けて入れる)、JS・TS [a[i], a[j]] = [a[j], a[i]](分割代入 — 前の行の末尾に ; がないと x\n[a[i], …] が x[…] とつながって読まれるので注意)、C# (a[i], a[j]) = (a[j], a[i])(タプル、C# 7 から)、C++ std::swap(a[i], a[j])。
Java・C・Craykon にはこの文法がないので一時変数を使います:tmp = a[i]; a[i] = a[j]; a[j] = tmp;。
いちばん多い落とし穴は一時変数なしで a[i] = a[j]; a[j] = a[i]; と書くこと — 一行目で a[i] の元の値が消え、二つのマスが同じになります。
二つ目は入れ替えを関数に出すこと:Java swap(int x, int y) と C swap(int x, int y) は値のコピーを受け取るので配列はそのままです。
C はポインタ swap(int *x, int *y)、Java は配列と二つの番号を渡す必要があり、C++ は参照 int& なので std::swap が使えます。
三つ目は XOR の小技 x ^= y; y ^= x; x ^= y;:i と j が同じマスだと自分自身と XOR して 0 になります — 例 2 のように同じ位置を入れ替える行があります。

Pythonmain.py · 7 行
n, m = map(int, input().split())cards = list(map(int, input().split()))for _ in range(m):    i, j = map(int, input().split())    # 오른쪽이 먼저 다 계산된 뒤 왼쪽에 담기므로 임시 변수가 필요 없다    cards[i - 1], cards[j - 1] = cards[j - 1], cards[i - 1]print(*cards)
JavaScriptmain.js · 9 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const [n, m] = lines[0].trim().split(/\s+/).map(Number);const cards = lines[1].trim().split(/\s+/).map(Number);for (let k = 0; k < m; k++) {  const [i, j] = lines[2 + k].trim().split(/\s+/).map((s) => Number(s) - 1);  // 구조 분해 대입: 오른쪽 배열을 먼저 만든 뒤 나눠 담는다  [cards[i], cards[j]] = [cards[j], cards[i]];}console.log(cards.join(" "));
TypeScriptmain.ts · 10 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const [n, m]: number[] = lines[0].trim().split(/\s+/).map(Number);const cards: number[] = lines[1].trim().split(/\s+/).map(Number);for (let k = 0; k < m; k++) {  const [i, j]: number[] = lines[2 + k].trim().split(/\s+/).map((s) => Number(s) - 1);  // 구조 분해 대입: 오른쪽 배열을 먼저 만든 뒤 나눠 담는다  [cards[i], cards[j]] = [cards[j], cards[i]];}console.log(cards.join(" "));
JavaMain.java · 31 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.StringTokenizer; public class Main {    public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        StringTokenizer st = new StringTokenizer(in.readLine());        int n = Integer.parseInt(st.nextToken());        int m = Integer.parseInt(st.nextToken());        int[] cards = new int[n];        st = new StringTokenizer(in.readLine());        for (int k = 0; k < n; k++) cards[k] = Integer.parseInt(st.nextToken());        for (int k = 0; k < m; k++) {            st = new StringTokenizer(in.readLine());            int i = Integer.parseInt(st.nextToken()) - 1;            int j = Integer.parseInt(st.nextToken()) - 1;            // Java에는 한 줄 바꾸기가 없어 임시 변수를 쓴다            int tmp = cards[i];            cards[i] = cards[j];            cards[j] = tmp;        }        StringBuilder out = new StringBuilder();        for (int k = 0; k < n; k++) {            if (k > 0) out.append(' ');            out.append(cards[k]);        }        System.out.println(out);    }}
C#Main.cs · 19 行
using System;using System.Linq; class Program{    static void Main()    {        int m = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray()[1];        int[] cards = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();        for (int k = 0; k < m; k++)        {            int[] ij = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();            int i = ij[0] - 1, j = ij[1] - 1;            // 튜플로 한 번에 바꾼다(C# 7부터)            (cards[i], cards[j]) = (cards[j], cards[i]);        }        Console.WriteLine(string.Join(" ", cards));    }}
C++main.cpp · 17 行
#include <iostream>#include <utility>#include <vector> int main() {    int n, m;    std::cin >> n >> m;    std::vector<int> cards(n);    for (int& c : cards) std::cin >> c;    for (int k = 0; k < m; k++) {        int i, j;        std::cin >> i >> j;        std::swap(cards[i - 1], cards[j - 1]);  // 참조로 받아 바꾼다    }    for (int k = 0; k < n; k++) std::cout << (k ? " " : "") << cards[k];    std::cout << '\n';}
Cmain.c · 19 行
#include <stdio.h> int main(void) {    int n, m;    static int cards[1000];    scanf("%d %d", &n, &m);    for (int k = 0; k < n; k++) scanf("%d", &cards[k]);    for (int k = 0; k < m; k++) {        int i, j;        scanf("%d %d", &i, &j);        /* 임시 변수에 한쪽을 먼저 맡겨 둔다 */        int tmp = cards[i - 1];        cards[i - 1] = cards[j - 1];        cards[j - 1] = tmp;    }    for (int k = 0; k < n; k++) printf(k ? " %d" : "%d", cards[k]);    printf("\n");    return 0;}
Craykonmain.cray · 14 行
첫줄 = コンソール.数読み();m = 첫줄[1];카드 = コンソール.数読み();繰り返す (k = 0; k < m; k++){    자리 = コンソール.数読み();    i = 자리[0] - 1;    j = 자리[1] - 1;    // 한쪽을 먼저 임시로 맡겨 둔다    임시 = 카드[i];    카드[i] = 카드[j];    카드[j] = 임시;}コンソール.書く(카드);