1つの問題を考えると、次のタスクを解決する効率的なアルゴリズムを作成する必要があることに気付きました。
問題:辺が軸に平行な辺 2次元の正方形の箱が与えられます。頂上から見ることができます。ただし、水平セグメントもあります。各セグメントには整数座標()および()があり、ポイントおよび(下の写真)。m個のY 0 ≤ Y ≤ N X 0 ≤ X 1 < X 2 ≤ N (X 1、Y )、 (X 2、Y )
ボックスの上部にある各ユニットセグメントについて、このセグメントを覗いた場合にボックス内をどのくらい深く見ることができるかを知りたいと思います。
正式には、場合、。
例:次の図のようにおよびセグメントがある場合、結果はです。箱の中にどれだけ深い光が入るかを見てください。
幸いなことに、とはどちらも非常に小さく、オフラインで計算を行うことができます。
この問題を解決する最も簡単なアルゴリズムはブルートフォースです。各セグメントでアレイ全体を走査し、必要に応じて更新します。ただし、O(mn)はあまり印象的ではありません。
大幅な改善は、クエリ中にセグメントの値を最大化し、最終値を読み取ることができるセグメントツリーを使用することです。これ以上は説明しませんが、時間の複雑さはことがわかります。
しかし、私はより速いアルゴリズムを思いつきました:
概要:
座標の降順にセグメントをソートします(カウントソートのバリエーションを使用した線形時間)。ここで、以前にユニットセグメントがいずれかのセグメントでカバーされていた場合、後続のセグメントは、このユニットセグメントを通過する光線をバインドできなくなります。次に、ボックスの上部から下部へのラインスイープを実行します。
それでは、いくつかの定義を紹介しましょう: -unitセグメント掃引上の仮想水平セグメントである -coordinates整数であり、長さが1の掃引プロセス中に各セグメントでは、いずれであってもよいマークされていないから行く光ビームです(ボックスの上部がこのセグメントに到達するか、マークされているか(反対のケース)。常にマークされていない、ユニットセグメントを考えます。セットも導入しましょう。各セットは、連続の全配列が含まれますマーク以下で(もしあれば)セグメントを-unit 無印 セグメント。
これらのセグメントとセットを効率的に操作できるデータ構造が必要です。最大のユニットセグメントインデックス(マークされていないセグメントのインデックス)を保持するフィールドによって拡張されたfind-union構造を使用します。
これで、セグメントを効率的に処理できます。ここで、で始まりで終わる番目のセグメントを順番に検討しているとしましょう(「クエリ」と呼びます)。番目のセグメント内に含まれる、マークされていないすべてのユニットセグメントを見つける必要があります(これらは、光ビームが途中で終了するセグメントです)。以下を実行します。まず、クエリ内で最初のマークされていないセグメントを見つけます(が含まれるセットの代表を見つけ、このセットの最大インデックスを取得します。これは定義によりマークされていないセグメントです)。次に、このインデックス クエリ内にある場合、結果に追加し(このセグメントの結果は)、このインデックスをマークします(とを含むUnionセット)。次に、すべてのマークされていないセグメントが見つかるまでこの手順を繰り返します。つまり、次の検索クエリはインデックスます。
各検索共用体操作は2つの場合にのみ行われることに注意してください。セグメントの検討を開始する(これは回発生する)か、ユニットセグメントをマークしただけです(これは回発生する可能性があります)。したがって、全体的な複雑さは(は逆アッカーマン関数です)。不明な点がある場合は、これについて詳しく説明します。時間があれば、写真を追加できるかもしれません。
今、私は「壁」に到達しました。私は線形アルゴリズムを思い付くことができませんが、線形アルゴリズムがあるはずです。だから、私は2つの質問があります:
- 水平セグメントの可視性の問題を解決する線形時間アルゴリズム(つまり、)はありますか?
- そうでない場合、可視性の問題があるという証拠は何ですか?