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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

1回答

1140閲覧

AtCoder ABC127-D 実行時間を短縮したい

amatsukixprog

総合スコア17

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2019/05/25 15:17

編集2019/05/28 13:04

前提・実現したいこと

ABC127-D
AtCoderのABC-D問題です。
他の方が書かれたコードや解説を参考にコードを修正しましたが、
7つ目のテスト項目においてTLEになってしまいます。
実行時間を短縮するために、下記のコードで修正できる箇所はありますでしょうか。

該当のソースコード

Ruby

1N,M=gets.chomp.split.map(&:to_i) 2A=gets.chomp.split.map(&:to_i) 3c=M.times.map { gets.split.map(&:to_i) } 4c.sort_by!{|i,j| j }.reverse! 5A.sort! 6 7M.times do |i| 8 next if A[0]>c[i][1] 9 c[i][0].times do |j| 10 break if A[0]>c[i][1] 11 A.shift() 12 A.push(c[i][1]) 13 end 14end 15puts A.inject(:+) 16

修正したコード

Ruby

1N,M=gets.chomp.split.map(&:to_i) 2A=gets.chomp.split.map(&:to_i) 3c=M.times.map { gets.split.map(&:to_i) } 4c.sort_by!{|i,j| j }.reverse! 5A.sort! 6sum=0 7M.times do |i| 8 break if A[0]>c[i][1] 9 b = 0 10 c[i][0].times do |j| 11 break if A[j]>c[i][1] 12 b += 1 13 end 14 A.shift(b) 15 sum += c[i][1]*b 16end 17puts (A.inject(:+)+sum)

修正したコード2

Ruby

1N,M=gets.chomp.split.map(&:to_i) 2A=gets.chomp.split.map(&:to_i) 3c=M.times.map { gets.split.map(&:to_i) } 4c.sort_by!{|i,j| j }.reverse! 5A.sort! 6sum=0 7M.times do |i| 8 break if A.empty? || A[0]>c[i][1] 9 b = 0 10 c[i][0].times do |j| 11 break if A[j]>c[i][1] 12 b += 1 13 end 14 A.shift(b) 15 sum += c[i][1]*b 16end 17if A.empty? then 18 puts sum 19else 20 puts (A.inject(:+)+sum) 21end

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

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

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

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

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

guest

回答1

0

ベストアンサー

Array#shiftを何度も行っているのが気になります。

c[i][0].times do |j|
break if A[0]>c[i][1]
A.shift()
A.push(c[i][1])
end

ruby

1b = 0 2c[i][0].times do |j| 3 break if A[j]>c[i][1] 4 b += 1 5end 6A.shift(b) 7A.push(*([c[i][1]]*b))

さらに、Array#bsearch_indexを用いる事でAが巨大な配列だった場合に高速化できる可能性がありますが
Nがたかだか10万なので、Aがソートされた状態なのを維持する手間に見合うかは微妙です。

投稿2019/05/25 21:10

asm

総合スコア15147

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

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

asm

2019/05/25 21:22

ついでに > next if A[0]>c[i][1] break if A[0]>c[i][1] でいいですね
amatsukixprog

2019/05/28 01:46

返信遅くなりまして申し訳ありません。 複数点、指摘していただき、ありがとうございます。 配列の掛け算ができることを初めて知りました。 修正し、テストいたしましたが同じところで、 TLEとなってしまいました。 他にも修正できる箇所はありますでしょうか。
asm

2019/05/28 05:03

cを降順ソートしているので1度交換した数値を更に交換する事はないです。 よって、交換済み・交換対象ではない数値を隔離する事でshift/pushによってコピーされる配列を小さくできます。 もっといえば、交換後の数値を配列に保存する必要はなく、交換後の数値の総和だけ持っていれば計算可能です。
amatsukixprog

2019/05/28 11:58

ありがとうございます! コードを修正しましたが、次はREが複数発生してしまいました。。。 よろしければご確認いただけないでしょうか。 修正したコード を追記致しました。
asm

2019/05/28 12:08

> break if A[0]>c[i][1] Aが空配列になるパターンを考慮していないようです。 break if A.empty? || A[0]>c[i][1] ですね
amatsukixprog

2019/05/28 13:08

ありがとうございます。 指摘していただいた部分と最後の出力の部分も考慮できていなかったため修正いたしましたが、 REが1つだけ残っていました。 他に問題点はありますでしょうか。。。 修正したコード2を追記致しました
asm

2019/05/28 13:34

出力部分については puts (A.inject(:+)||0)+sum でよかったりしますね。 他のエラーはちょっと見つかりませんね・・・ なんだろ
amatsukixprog

2019/05/28 13:44

||で左から順に判定してくれるんですね。初めて知りました。。。 色々書き方を知ることができてよかったです。 教えてくださりありがとうございました。 また自力で探してみたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問