パッド2の乗に出て、配列、ゼロを追加することによって。次に、それをスタックにピラミッド化し、毎回各次元で2倍に縮小します。各レベルで、各要素の値は、ピラミッド内の次に大きい配列の4つの対応する要素の最大値に等しくなります。これは、ミップマップのように、パディングされた配列サイズの上に追加の1/3の記憶スペースを必要とします。
与えられた配列レベルの単一の要素をとり、クエリ領域がそれによってカバーされる境界をカバーするかどうかを調べる再帰関数を作成します。そうでない場合は、クエリ領域と重なる次の最大配列の各領域をチェックし、それぞれの再帰的に計算された最大値を返します。
擬似コード:
int getMax(Rect query_rect, int level, int level_x, int level_y)
{
int level_factor = 1 << level;
// compute the area covered by this array element:
Rect level_rect(level_x * level_factor, level_y * level_factor,
(level_x + 1) * level_factor, (level_y + 1) * level_factor);
// if the regions don't overlap then ignore:
if(!query_rect.intersects(level_rect))
return -1;
// query rect entirely contains this region, return precomputed max:
if(query_rect.contains(level_rect))
return pyramid[level][level_x][level_y];
if(level == 0)
return -1; // ran out of levels
int max = getMax(query_rect, level - 1, level_x * 2, level_y * 2);
max = maxValue(max, getMax(query_rect, level - 1, (level_x * 2) + 1, level_y * 2);
max = maxValue(max, getMax(query_rect, level - 1, level_x * 2, (level_y * 2) + 1);
max = maxValue(max, getMax(query_rect, level - 1, (level_x * 2) + 1, (level_y * 2) + 1);
return max;
}
最初にトップレベル(ピラミッドで絶頂の1x1のアレイ)でそれを呼び出す:
int max = getMax(query_rect, 10, 0, 0);
以下、クエリ矩形の最小サイズがありますそれはすべての要素を反復するだけで安くなるでしょう。これを非正方配列でも使えるように変更することができます。再帰するときは、各レベルの配列サイズに対していくつかの追加テストが必要になります。
矩形のサイズは可変ですか? –
最大操作と加算の間には大きな違いがあります。最大値は不可逆です。 max(a、b)を取った後、2つの数のうちの1つが永遠に失われます。これはa + bとは対照的で、aを知ることができるようになります。このため、「積分画像」トリックは使用できません。 –
おそらく[2次元範囲の最小クエリ](https://www.researchgate.net/publication/221314133_Two-Dimensional_Range_Minimum_Queries)があなたが探しているものです。 –