web-dev-qa-db-ja.com

ツリーでXOR和を見つける

私は解決しようとしていました hackerearthでのこの問題 各ノードに値を持つツリーがあり、2つのノード間のxor合計を尋ねるクエリに答える必要があります。また、更新が必要です(ノードの値は変更される可能性があります)。簡単な部分(dfsとlca)を解決し、各ノードについて、ノード1からそのノード(そのノードを含む)へのパス上のノードの値のxor合計を保存しました。

ただし、この問題については理解できない「社説」の一部があります。

ツリーがノード1をルートとしていると考えます。F(i)をXORルート1からノードへのパス内のノードに関連付けられたすべての値の合計にしますi。LCA(u、v)をノードuとノードvの最も低い共通祖先とする。Q(u、v)をXOR単一のノードに関連付けられたすべての値の合計とするノードuからノードvへのパス。したがって、Q(u、v)はタイプ2の各クエリに対する回答です。

Q(u、v)= F(u) XOR F(v) XOR A [LCA(u、v)](理由)ここで、A [i]はノードiに関連付けられた値を示します。

私は彼らがこの式をどこで得たのか分かりません:

Q(u、v)= F(u) XOR F(v) XOR A [LCA(u、v)]

この公式の背後にある思考プロセスは何ですか?

3
Joen Don

その式を導き出すための鍵は、さまざまなパスがどのように重なり合うかを確認し、任意の数値XOR自体が0に等しいことを思い出すことです。特に、 Q(x、y)XOR Q(x、y)も0になります。

クイック派生

F(u)は、ルートノードからuへのパスです。 F(v)はルートノードからvへのパスです。任意の数値XOR自体は0に等しいため、F(u) XOR F(v)は、uとvの共通の最下位祖先、LCA(u、v)より上のすべてのノードを「キャンセル」します。したがって、F(u) XOR F(v) = Q(LCA(u、v)、u)XOR Q(LCA (u、v)、v)。これは、LCA(u、v)自体を除いて、uからvへの一意のパス上のすべてのノードのXOR合計です。これは、現在2回カウントされているためです。したがって、単純に3回カウントすると、Q(u、v)のすべてのノードの合計が得られます。したがって、Q(u、v)= F(u) XOR F(v) XOR LCA(u、v)。

この「証明」には、あまりにも多くの詳細が省略されているか、まだ確信が持てないいくつかの手順が含まれているのではないかと思います。

徹底的な導出

グラフが有効なツリーであり、uとvの間に一意の単一のパスがあると仮定しています。これにより、uとvに単一の「最も低い共通の祖先」LCA(u、v)が存在することが保証されます。として。ルートノードをrと呼びます。 aは、u、v、a、または3つすべてと同じノードである場合があることに注意してください。私がこれから提示しようとしている議論は、これらの退化した場合でも依然として機能するはずです。

したがって、これらの4つのノード間には、次のような一意のパス(長さがゼロの可能性があります)があります。

enter image description here

「社説」に従い、Q(x, y)は、xからyへの一意のパス上のノードのXOR合計を示します。

Q(u, v)に興味があります。明らかに、uからvへの一意のパスはaを通過します。ただし、aの値を2回カウントするため、Q(u, v) = Q(u, a) XOR Q(a, v)と言うのは誤りです。幸い、値自体をXORするとゼロになるため、aを3回カウントすることは、1回だけカウントすることと同じです。したがって、正しいステートメントは次のとおりです。

_Q(u, v) = Q(u, a) XOR Q(a, v) XOR A[a]
_

次に、F(i)Q(r, i)として定義されます。したがって、上記と同じロジックに従い、次のように言うことができます。

_F(u) = Q(r, u) = Q(r, a) XOR Q(a, u) XOR A[a]
F(v) = Q(r, v) = Q(r, a) XOR Q(a, v) XOR A[a]
_

さて、F(u) XOR F(v)とは何ですか? XOR演算は可換的かつ連想的であるため、一連の+ sのように一連のXORを安全に再配置できます。これにより、次のことが可能になります。

_F(u) XOR F(v) = (Q(r, a) XOR Q(a, u) XOR A[a]) XOR (Q(r, a) XOR Q(a, v) XOR A[a])
              = (Q(r, a) XOR Q(r, a)) XOR (Q(a, u) XOR Q(a, v)) XOR (A[a] XOR A[a])
              = 0 XOR (Q(a, u) XOR Q(a, v)) XOR 0
              = Q(a, u) XOR Q(a, v)
_

より直感的に:重複する2つのパスのXOR XORの合計を行うと、重複する部分が単に消えて、XORの合計のみが残ります。パスの重複しない部分。

最後に、そのQ(u, v) = Q(u, a) XOR Q(a, v) XOR A[a]を思い出してください。 Q(a, u) XOR Q(a, v)F(u) XOR F(v)と等しいことがわかりました。つまり、

_Q(u, v) = Q(u, a) XOR Q(a, v) XOR A[a]
        = F(u) XOR F(v) XOR A[a]
_

そして、aLCA(u, v)として定義したので、完了です。

3
Ixrec