0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

平方分割

https://paiza.jp/works/mondai/query_primer/query_primer__square_division
Java初学者ですが、こちらの問題を頑張って解きました。
PythonやCでの解説記事はよく見かけるものの、Javaで攻略している記事をあまり見かけない為、記念に残しておこうと思います。

当初、テスト1と4は通るのに、テスト2と3がランタイムエラーになるため、その原因探しに苦しみました。
ブロックごとの計算におけるforループの記述に問題があったわけですが、
気づくまで大変時間がかかった。

感想

平方分割というアルゴリズムを初めて知ったので、物凄く勉強になりました。
当初、分割しただけじゃ計算量そこまで変わらないのでは〜?と思っておりましたが、
予め計算済みの配列を用意しておくことで、範囲内の計算をスキップ出来るわけですね。

以下、問題なくパスしたコード。

Main.java
import java.util.*;

public class Main{
    int[] array;    //元の配列
    int[] blocks;   //ブロックごとの最大値を格納
    int blockSize;
    
    public Main(int[] array){
        this.array = array;
        blockSize = (int)Math.sqrt(array.length);
        int blockCount = (array.length + blockSize -1)/blockSize;
        blocks = new int[blockCount];
        
        Arrays.fill(blocks, Integer.MIN_VALUE);
        
        //ブロックごとの最大値を計算
        for(int i=0; i<array.length; i++){
            blocks[i/blockSize] = Math.max(blocks[i/blockSize], array[i]);
        }
    }
    
    public int queryMax(int l, int r){
        int block_l = (l-1)/blockSize;
        int block_r = (r-1)/blockSize;
        int max = Integer.MIN_VALUE;
        
        //同じブロックの場合
        if(block_l == block_r){
            for(int i=l-1; i<=r-1; i++){
                max = Math.max(max, array[i]);
            }
        }else{
            //leftブロックを計算
            for(int i=l-1; i<(block_l+1)*blockSize && i<array.length; i++){
                max = Math.max(max, array[i]);
            }
            
            //中間ブロックを計算
            for(int i=block_l+1; i<block_r; i++){
                max = Math.max(max, blocks[i]);
            }
            
            //rightブロックを計算
            for(int i=block_r*blockSize; i<=r-1 && i<array.length; i++){
                max = Math.max(max, array[i]);
            }
        }
        
        return max;
    }
    
    public static void main(String... args){
        Scanner sc = new Scanner(System.in);
        int n = 10000;
        int k = sc.nextInt();
        
        int[] input = new int[n];
        for(int i=0; i<n; i++){
            input[i] = sc.nextInt();
        }
        
        Main m = new Main(input);
        
        for(int i=0; i<k; i++){
            int l = sc.nextInt();
            int r = sc.nextInt();
            System.out.println(m.queryMax(l, r));
        }
        
        sc.close();
    }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?