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

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

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

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

1265閲覧

Paizaの平方分割がタイムアウトになる。

takuma0306

総合スコア1

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2023/08/23 10:07

編集2023/08/23 11:02

問題リンク

https://paiza.jp/works/mondai/query_primer/query_primer__square_division

現状

現在PaizaにおいてJavaの学習を進めています。

その中で平方分割について学んでおり、「長さ10000の数列Aと3つの区間が与えられ、その区間に置けるそれぞれの最大値を出力する」という問題で実行時間を縮めることができずに困っています。

該当のソースコード

Java

1import java.util.*; 2 3public class Main { 4 public static void main(String[] args) throws Exception { 5 Scanner sc = new Scanner(System.in); 6 7 int K = sc.nextInt(); 8 9 int[] array = new int[10000]; 10 int[] rangeMax = new int[100]; 11 12 for(int i=0; i<10000; i++){ 13 array[i] = sc.nextInt(); 14 } 15 16 for(int i=0; i<100; i++){ 17 int min = -100000; 18 int start = i * 100; 19 int end = (i + 1) * 100; 20 21 for(int j=start; j<end; j++){ 22 if(array[j] >= min){ 23 min = array[j]; 24 } 25 } 26 27 rangeMax[i] = min; 28 } 29 30 for(int i = 0; i < K; i++){ 31 int left = sc.nextInt() - 1; 32 int right = sc.nextInt() - 1; 33 int now = left; 34 int ans = array[left]; 35 36 while(now <= right){ 37 if((now % 100 == 0) & (now + 100 - 1 <= right)){ 38 if(ans <= rangeMax[now / 100]){ 39 ans = rangeMax[now / 100]; 40 } 41 } 42 else{ 43 if(ans <= array[now]){ 44 ans = array[now]; 45 now++; 46 } 47 } 48 } 49 50 System.out.println(ans); 51 } 52 } 53}

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

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

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

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

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

meg_

2023/08/23 10:26

> ランタイムエラーになる。 > 実行時間を縮めることができずに困っています。 エラーなのですか?タイムアウトなんですか??
jimbe

2023/08/23 10:48

平方分割ならせめてルートは使ったほうが良いのでは。 いくら例が 10000 件だからと言って 100 をベタ書きしては「『平方分割』を学ぶプログラム」としてはそもそもダメな気がしますが。
takuma0306

2023/08/23 10:50 編集

meg_さん。 タイムアウトになってしまいます。
takuma0306

2023/08/23 10:50

jimbeさん。 アドバイスありがとうございます。 修正します!
meg_

2023/08/23 10:58

> タイムアウトになってしまいます。 そうであればタイトルが紛らわしいので修正された方が良いかと思います。
takuma0306

2023/08/23 11:02

タイトル修正しました。
guest

回答2

0

最後のwhile文ですが

java

1 while(now <= right){ 2 if((now % 100 == 0) & (now + 100 - 1 <= right)){ 3 if(ans <= rangeMax[now / 100]){ 4 ans = rangeMax[now / 100]; 5 } 6 // ※※ここ 7 } 8 else{ 9 if(ans <= array[now]){ 10 ans = array[now]; 11 now++; 12 } 13 // ※※ここの省略されたelse 14 } 15 }

コメントを入れた分岐では now も right も書き換えられず、1度でもそこに入ったら無限ループするのではないでしょうか?

投稿2023/08/23 12:05

pecmm

総合スコア760

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

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

takuma0306

2023/08/23 12:49

pecmmさん! ありがとうございます。 解決できました!
guest

0

ベストアンサー

36~48行目の while は now の加算が if の奥深くに 1 つあるだけですけど、どのような場合でもちゃんとループが終わるでしょうか?


1 つのループ内でイロイロ判断するよりも 3 つに分けてやったほうが分かり易い気がします。

java

1import java.util.*; 2 3public class Main { 4 public static void main(String[] args) throws Exception { 5 Scanner sc = new Scanner(System.in); 6 7 int n = 10000; 8 9 int k = sc.nextInt(); 10 11 int[] a = new int[n]; 12 int x = (int)Math.sqrt(n); 13 int[] r = new int[x+1]; //+1 は最期の x 個に満たない分用. 不使用 14 15 for (int i=0, ii=0; i<n; ii++) { 16 r[ii] = Integer.MIN_VALUE; 17 for (int j=0; j<x && i<n; i++, j++) { 18 a[i] = sc.nextInt(); 19 r[ii] = Math.max(r[ii], a[i]); 20 } 21 } 22 23 for (int i=0; i<k; i++) { 24 int s = sc.nextInt() - 1; //含む 25 int e = sc.nextInt(); //含まない 26 27 int rs = (s+x-1) / x; //含む 28 int re = e / x; //含まない 29 30 int v = Integer.MIN_VALUE; 31 if(rs >= re) { 32 v = max(a, s, e, v); 33 } else { 34 v = max(a, s, rs*x, v); 35 v = max(r, rs, re, v); 36 v = max(a, re*x, e, v); 37 } 38 System.out.println(v); 39 } 40 } 41 //配列 a のインデックス s (含む)から e (含まない)の範囲の値と v のうちの、最大値を返す 42 private static int max(int[] a, int s, int e, int v) { 43 for(int i=s; i<e; i++) v = Math.max(v, a[i]); 44 return v; 45 } 46}

投稿2023/08/23 12:09

編集2023/08/23 19:50
jimbe

総合スコア13327

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

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

takuma0306

2023/08/23 12:51

jimbeさん! ありがとうございます。 自分で書いたコードよりはるかに見やすく、わかりやすいです!
jimbe

2023/08/23 19:01 編集

すみません、バグがありました。 1 つは、 s~e の範囲に e が含まれていませんでした。 もう 1 つは、常に3つのループをするようでは例えば x=100 の時の s=10, e=20 のように x の 1 つの範囲に収まる場合に rs=1, re=0 となり、 1 つ目のループで 10~100、3 つ目のループで 0~20 を対象にしてしまいます。rs と re の関係によっては単純に s~e をループするようにしました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問