{ }codelper
要素の入れ替えリストの並べ替えリストの切り出しP0177

倉庫の棚を区間ごとに整理

倉庫の棚の一列に箱が n 個置かれていて、枠番号は左から 1, 2, …, n である。
二行目に枠の順に箱の重さ n 個が与えられる。
三行目に命令の数 q が、続く q 行に命令が一つずつ与えられる。
命令は三種類ある。
「swap i j」は i 番の枠と j 番の枠の箱を交換する(i と j が同じならそのままで、i が j より大きいこともある)。
「sort l r」は l 番から r 番まで(両端を含む)の箱だけを、軽いものが左に来るように並べ替える。
この区間の外の箱は動かない。
「show l r」は今の l 番から r 番まで(両端を含む)の重さを空白一つずつ区切って一行に出力する。
show 命令ごとに一行ずつ、命令の順に出力せよ。

入力
1 ≤ n ≤ 1000、1 ≤ q ≤ 1000、1 ≤ 重さ ≤ 1,000,000(整数)。
swap は 1 ≤ i, j ≤ n、sort・show は 1 ≤ l ≤ r ≤ n。
show 命令は少なくとも一つあり、show で出力する重さは合わせて 20,000 個以下
出力
show 命令ごとに一行
例 1 · stdin
6
30 4 100 25 9 7
5
sort 2 5
show 1 6
swap 1 6
sort 4 6
show 3 5
stdout
30 4 9 25 100 7
9 25 30
例 2 · stdin
3
5 1 3
4
show 2 2
swap 3 3
sort 1 1
show 1 3
stdout
1
5 1 3
main.py
入力(stdin)

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

$ 準備完了

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

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

リストの一区間を切り出して並べ替える方法は、言語によって「終わりを含むか」「コピーかその場か」で分かれます。
1 から数えた l ~ r(両端を含む)の切り出し:Python a[l-1:r]、JS・TS a.slice(l-1, r)、Java Arrays.copyOfRange(a, l-1, r)(三つとも終わりの位置は含みません)、C# の範囲 a[(l-1)..r](これも終わりは除きます)、Craykon a.部分リスト(l-1, r-l+1)(韓国語 부분목록、開始と個数)。
区間の並べ替え:Java Arrays.sort(a, l-1, r) と C++ std::sort(a.begin()+l-1, a.begin()+r) は終わりを除いてその場で並べ替え、C# Array.Sort(a, l-1, r-l+1) と C qsort(a+l-1, r-l+1, …) は開始と個数を受け取ります。
落とし穴その一:Python a[l-1:r].sort() は切り出したコピーを並べ替えて捨てるので、棚はそのままです。
a[l-1:r] = sorted(a[l-1:r]) のように戻します。
Craykon の 部分リスト も新しいリストなので並べ替えたあと一つずつ書き戻し、JS は splice で戻します。
落とし穴その二:JS・TS の sort() に比較関数を渡さないと数を文字列にして比べるので、[10, 9, 100] が [10, 100, 9] になります。
sort((u, v) => u - v) を使います。
落とし穴その三:C# Array.Sort(a, 開始, 終わり) のように三つ目に終わりの位置を渡すと個数が違うので、区間の外まで並べ替えたりエラーになったりします。
落とし穴その四:a[l-1:r-1] のように一つ短く切ると r 番の枠が抜けます。
二つの枠の交換は Python a[i], a[j] = a[j], a[i]、JS・TS の分割代入、C# のタプル、C++ std::swap、Java・C・Craykon は一時変数です。

Pythonmain.py · 18 行
import sys lines = sys.stdin.read().split("\n")n = int(lines[0])shelf = list(map(int, lines[1].split()))q = int(lines[2])out = []for line in lines[3:3 + q]:    cmd, a, b = line.split()    a, b = int(a) - 1, int(b)          # 0부터 세는 시작 a, 끝 b(b는 들어가지 않음)    if cmd == "swap":        i, j = a, b - 1        shelf[i], shelf[j] = shelf[j], shelf[i]    elif cmd == "sort":        shelf[a:b] = sorted(shelf[a:b])  # 잘라 낸 것은 사본이라 정렬한 뒤 그 자리에 다시 넣는다    else:        out.append(" ".join(map(str, shelf[a:b])))print("\n".join(out))
JavaScriptmain.js · 19 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const shelf = lines[1].trim().split(/\s+/).map(Number);const q = Number(lines[2]);const out = [];for (const line of lines.slice(3, 3 + q)) {  const [cmd, x, y] = line.trim().split(" ");  const a = Number(x) - 1;  const b = Number(y); // slice(a, b)는 b를 넣지 않는다  if (cmd === "swap") {    [shelf[a], shelf[b - 1]] = [shelf[b - 1], shelf[a]];  } else if (cmd === "sort") {    // 비교 함수가 없으면 문자열로 비교해서 "10" < "9"가 된다    const part = shelf.slice(a, b).sort((u, v) => u - v);    shelf.splice(a, part.length, ...part);  } else {    out.push(shelf.slice(a, b).join(" "));  }}console.log(out.join("\n"));
TypeScriptmain.ts · 20 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const shelf: number[] = lines[1].trim().split(/\s+/).map(Number);const q = Number(lines[2]);const out: string[] = [];for (const line of lines.slice(3, 3 + q)) {  const [cmd, x, y] = line.trim().split(" ");  const a = Number(x) - 1;  const b = Number(y); // slice(a, b)는 b를 넣지 않는다  if (cmd === "swap") {    [shelf[a], shelf[b - 1]] = [shelf[b - 1], shelf[a]];  } else if (cmd === "sort") {    // 비교 함수가 없으면 문자열로 비교해서 "10" < "9"가 된다    const part: number[] = shelf.slice(a, b).sort((u, v) => u - v);    shelf.splice(a, part.length, ...part);  } else {    out.push(shelf.slice(a, b).join(" "));  }}console.log(out.join("\n"));
JavaMain.java · 29 行
import java.io.*;import java.util.*; public class Main {    public static void main(String[] args) throws IOException {        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        int n = Integer.parseInt(br.readLine().trim());        int[] shelf = Arrays.stream(br.readLine().trim().split(" ")).mapToInt(Integer::parseInt).toArray();        int q = Integer.parseInt(br.readLine().trim());        StringBuilder out = new StringBuilder();        for (int k = 0; k < q; k++) {            String[] p = br.readLine().trim().split(" ");            int a = Integer.parseInt(p[1]) - 1;            int b = Integer.parseInt(p[2]); // 끝 자리 b는 들어가지 않는다(toIndex)            if (p[0].equals("swap")) {                int tmp = shelf[a];                shelf[a] = shelf[b - 1];                shelf[b - 1] = tmp;            } else if (p[0].equals("sort")) {                Arrays.sort(shelf, a, b); // 그 구간만 제자리에서 정렬            } else {                StringJoiner sj = new StringJoiner(" ");                for (int w : Arrays.copyOfRange(shelf, a, b)) sj.add(String.valueOf(w));                out.append(sj).append('\n');            }        }        System.out.print(out);    }}
C#Main.cs · 32 行
using System;using System.Linq;using System.Text; class Program{    static void Main()    {        Console.ReadLine();        int[] shelf = Console.ReadLine().Trim().Split(' ').Select(int.Parse).ToArray();        int q = int.Parse(Console.ReadLine().Trim());        var sb = new StringBuilder();        for (int k = 0; k < q; k++)        {            string[] p = Console.ReadLine().Trim().Split(' ');            int a = int.Parse(p[1]) - 1, b = int.Parse(p[2]) - 1; // 둘 다 0부터, b도 들어간다            if (p[0] == "swap")            {                (shelf[a], shelf[b]) = (shelf[b], shelf[a]);            }            else if (p[0] == "sort")            {                Array.Sort(shelf, a, b - a + 1); // (시작, 개수)다. 끝 자리가 아니다            }            else            {                sb.Append(string.Join(" ", shelf[a..(b + 1)])).Append('\n'); // 범위 a..c 는 c를 넣지 않는다            }        }        Console.Write(sb);    }}
C++main.cpp · 29 行
#include <algorithm>#include <iostream>#include <string>#include <utility>#include <vector> int main() {    std::ios::sync_with_stdio(false);    int n, q;    std::cin >> n;    std::vector<int> shelf(n);    for (int& w : shelf) std::cin >> w;    std::cin >> q;    std::string out;    for (int k = 0; k < q; k++) {        std::string cmd;        int a, b;        std::cin >> cmd >> a >> b;        if (cmd == "swap") {            std::swap(shelf[a - 1], shelf[b - 1]);        } else if (cmd == "sort") {            std::sort(shelf.begin() + (a - 1), shelf.begin() + b); // [첫, 끝) — 끝은 들어가지 않는다        } else {            for (int i = a - 1; i < b; i++) out += (i > a - 1 ? " " : "") + std::to_string(shelf[i]);            out += "\n";        }    }    std::cout << out;}
Cmain.c · 32 行
#include <stdio.h>#include <stdlib.h> static int ascending(const void* x, const void* y) {    int a = *(const int*)x, b = *(const int*)y;    return (a > b) - (a < b);} int main(void) {    static int shelf[1000];    int n, q;    scanf("%d", &n);    for (int i = 0; i < n; i++) scanf("%d", &shelf[i]);    scanf("%d", &q);    for (int k = 0; k < q; k++) {        char cmd[8];        int a, b;        scanf("%7s %d %d", cmd, &a, &b);        a--, b--; /* 둘 다 0부터 */        if (cmd[1] == 'w') { /* swap */            int tmp = shelf[a];            shelf[a] = shelf[b];            shelf[b] = tmp;        } else if (cmd[1] == 'o') { /* sort: a번부터 (b - a + 1)칸 */            qsort(shelf + a, b - a + 1, sizeof shelf[0], ascending);        } else { /* show */            for (int i = a; i <= b; i++) printf(i > a ? " %d" : "%d", shelf[i]);            printf("\n");        }    }    return 0;}
Craykonmain.cray · 29 行
n = コンソール.行読み().数に();shelf = コンソール.数読み();q = コンソール.行読み().数に();繰り返す (k = 0; k < q; k++){    p = コンソール.行読み().空白除去().分ける();    a = p[1].数に() - 1;    b = p[2].数に() - 1; // 둘 다 0부터, b도 들어간다    もし (p[0] == "swap")    {        tmp = shelf[a];        shelf[a] = shelf[b];        shelf[b] = tmp;    }    でなければ もし (p[0] == "sort")    {        // 부분목록은 (시작, 개수)로 잘라 낸 새 목록이라, 정렬한 뒤 제자리에 다시 써 넣는다        part = shelf.部分リスト(a, b - a + 1);        part.並べ替え();        繰り返す (i = 0; i < part.個数; i++)        {            shelf[a + i] = part[i];        }    }    でなければ    {        コンソール.書く(shelf.部分リスト(a, b - a + 1).つなぐ(" "));    }}