質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

684閲覧

lst[i + 1] = i とならないようにする手順

kay_ventris4

総合スコア269

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/05/27 06:53

編集2021/05/27 07:14

#問題
イメージ説明
AtCoder ABC72 D問題より

#方針
① lst[i + 1] = i を満たしてしまっているような i (0 <= i <= N - 1) を探索し、lst[i] += 1 とする。

② 0が出現する区間に用はなく、1が出現する区間を、その区間の長さとともに data に格納する。

③ 区間の長さが1の時は、1回隣の要素とswapを行えば良いので、1を。区間の長さが2以上の時は、一番左の最小の要素を一番右まで持ってくる回数であるlen(list(v)) - 1を求める([..., 3,4,5, ...]となっているなら、[3,4,5]→[4,3,5]→[4,5,3](3 - 1 = 2回)のように)。

④ 以上を全ての1で出来た区間で行い、要したswapの回数を答えとして出力する。

#ソースコード

Python

1from itertools import groupby 2 3N = int(input()) 4p = list(map(int, input().split())) 5 6lst = [0] * N 7for i in range(N): 8 if i + 1 == p[i]: 9 lst[i] += 1 10 11data = [] 12for k, v in groupby(lst): 13 data.append([k, len(list(v))]) 14 15data = [el for el in data if el[0] == 1] 16 17cnt = 0 18for el in data: 19 if el[1] == 1: 20 cnt += 1 21 elif el[1] > 1: 22 cnt += el[1] - 1 23 24print(cnt)

#質問
サンプル入力や、手元で行った実験では全てうまくいったのですが、コードを提出するとごく一部のテストケースでバツを食らいます。古いコンテスト故にそのテストケースが公開されておらず、自分でも上の考え方のどこがどう間違っているのかが見えずにいます。いささか雑な形の質問となり恐縮ですが、お力添え頂ける箇所がございましたら、ご指摘のほどよろしくお願い申し上げます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

例えば、このような入力では誤答になります。

4 1 2 3 4

正解は2ですが、質問文のコードでは3になります。
(1-2、3-4の2回のswapで済みます)
③の長さ2以上の区間を処理する方法が誤っています。上の例の様に、1回swapすると1が連続する区間が2減るのに気づいてください。

なお、解説資料にはもっと簡潔に解法が書かれています。詰まったらそちらを読んでみるのも良いでしょう。

投稿2021/05/27 07:19

hope_mucci

総合スコア4447

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kay_ventris4

2021/05/27 07:25 編集

ご丁寧な回答ありがとうございます。 cnt = 0 for el in data:   cnt += math.ceil(el[1] / 2) として通りました。 実際のところは貪欲法を使えばO(N)で難なくいけたみたいですね。 これからも精度をあげていきたいと思います。ありがとうございました。
hope_mucci

2021/05/27 08:05

ACできて何よりです。 今回の様に、入力例では出てこない特殊なケースを見極めることも競技プログラミングは重要です。 ランダムな値だけでなく、入力境界値ややたら綺麗に並んだデータがWAやLTEを誘発する問題もあります。そのようなテストケースをぱっとおもいつけるのも1つの能力だと思います。
kay_ventris4

2021/05/27 08:07

確かにその通りですね。 特に詰まった時は原点に帰ってそうしたところもくまなく調査するように心がけたいと思います。
guest

0

ベストアンサー

例えば[..., 3, 4, 5, 6, ....]の場合、3と4、5と6を入れ替えて[..., 4, 3, 6, 5, ....]になればOKなので、2回でできます。

③ 区間の長さが1の時は、1回隣の要素とswapを行えば良いので、1を。区間の長さが2以上の時は、一番左の最小の要素を一番右まで持ってくる回数であるlen(list(v)) - 1を求める

が間違ってますね。

同様にいくつかのパターンで考えると、len(list(v)) - 1 ではなく、何が正しいか気づくと思います。

投稿2021/05/27 07:16

bsdfan

総合スコア4587

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kay_ventris4

2021/05/27 07:25 編集

cnt = 0 for el in data:   cnt += math.ceil(el[1] / 2) とすることでコードが通りました。 ありもしないルールを勝手に自分の中で作っていました。今後気をつけたいと思います。 ご丁寧にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問