リニアグループの正の解。
一般LCAおよびプレFとして[X] [i]はiがルートにステップと直鎖状の基を歩く$ X $ 2 ^までxは、
それは処理され、組み合わされ、線形ベースパスを取得するためにLCAのようにしてもよいです。
に進む前に。
しかし、私はしばしば前に、そして最終的にmemsetのATに変更したのに長い時間のための制御のmemset、カードカードを持っていません。
多くの場合、本当に嫌なカード。
#include <iostreamの> する#include <cstdioを> する#include <CStringの> する#include <cmath> の#defineクリア(A)のmemset((A).D、0、はsizeof((A).D)) 使用して 名前空間STDを、 typedefの長い 長いLL。 const int型 MAXN = 2E4 + 5 。 LLのN、Q、X、Y。 【MAXN、W LL。 チャーのxB [(1 << 15)+ 10 ]、* XS = xBで、* = xTのxBの; #define GTC(XS == xTの&&(Xtが=(XS =のxB)+関数fread(xBで、1,1 << 15、STDIN)、XS == xTの)0:* XS ++) インラインボイドリード(LL&X) { 登録チャー CH = GTC。 用(X = 0 ; CH < ' 0 ' || CH> ' 9 ' ; CH = GTC)。 用(; CH> = ' 0 ' && CH <= ' 9 ' ; X =(X << 1)+(X << 3)CH- + ' 0 '、CH = GTC)。 } インラインボイドプリント(LLのX) { 場合(X < 0){のputchar(' - ')。X = - X;} もし(X>)プリント(X / 10 )。 putchar(X%10 + 48 )。 返します。 } 構造体道路{ int型の TOT、T [MAXN << 1 ]、NXT [MAXN << 1 ]、最初の[MAXN]。 ボイド追加(int型のx、int型のY) { T [ ++ TOT = Y。 NXT [TOT] = 最初の[X]。 最初の[X] = TOTは、 } } EAGE。 構造体Least_Common_Ancetor { 構造体line_bsis { LLのD [63 ]。 ボイドインサート(LLのX) { ため(登録をint = I 61、I> = 0 ; i-- ) もし((X >> I)&1 ) { 場合(!D [i])と{D [I] =バツ; ブレーク;} X ^ = D [i]は、 } } LLミリアンペア() { LL ANS = 0 。 ため(登録をint iは= 61、I> = 0 ; i--) であれば((ANS ^ D [I])> ANS) ANS ^ = [I] D。 戻るANSを。 } } LB [MAXN] [ 30 ]、自[MAXN]、TMP、R。 int型 P、D [MAXN]、F [MAXN] [ 30 ]。 インラインline_bsisマージ(CONST line_bsis&、CONST line_bsis&B) { クリア(R) ため(登録をint iは= 60、I> = 0 ; i-- ) { 場合(AD [i])とr.insert(AD [I])。 もし(BD [I])r.insert(BD [I])。 } 戻りR。 } インラインボイド lmerge(line_bsis&、line_bsis&B) { ため(登録をint i = 60 ; I> = 0 ; - I) であれば(BD [i])と a.insert(BD [I])。 } ボイドのinit() { Pの =のLOG2(N)+ 1 。 以下のために(int型 I = 1 iが++; iが<= N 自身の[I] .insert(W [I]))。 DFS(1、0); } インラインボイド DFS(int型のx、int型FA) { ため(INT I = eage.first [X]; I; I = eage.nxt [I]) であれば(!eage.t [I] = FA) { int型 T = eage.t [I]。 D [T] = D [X] + 1 。 F [T] [ 0 ] = xを、LB [T] [ 0 ] = マージ(自[x]は、自身の[T])。 用(INTの J = 1 ; J <= P; J ++ ) { F [T] [J] = F [F [T] [J =1] [J- 1 ]。 もし(F [T] [j] == 0)ブレーク。 LB [T] [J] =マージ(LB [T] [J- 1 ]、LB [] T [F [J- 1 ]] [J- 1 ])。 } DFS(T、X)。 } } インラインINT LCA(int型のx、int型のY) { クリア(TMP)。 もし(D [X] < D [Y])スワップ(X、Y) INT T = D [X] - D [Y]。 以下のために(int型 I = Pを; T; i--) であれば(T&(1 << I)) { lmerge(TMP、LB [X] [I])。 X = F [X] [i]は、T ^ =(1つの << I)。 } もし(x == y)は戻りX。 以下のために(int型 = P Iを、I> = 0 ; i-- ) であれば(F [X] [I] ^ F [Y] [I]) { lmerge(TMP、LB [X] [I])。 lmerge(TMP、LB [Y] [I])。 X = F [X] [i]は、Yは= F [Y]を[I]。 } lmerge(TMP、LB [X] [ 0]); lmerge(TMP、LB [Y] [ 0 ])。 戻り [X] [F 0 ]。 } } ZT。 INT メイン() { (n)を読み出す;(Q)を読み込みます。 以下のために(int型 i = 1 ; iが<= N; iは++ )読み出す(W [I])。 以下のために(int型 I = 1 ; I <= N- 1、I ++ ) { (X)を読み出し、読み出され(y)を、 eage.add(X、Y); eage.add(Y、X)。 } zt.init()。 / * ため(; iがn = <; I = 1 int型I ++) のための(INT J = 0であり、j <= zt.p; J ++) COUT << I << ":" << J <<」「<< zt.lb [I] [J] .ma()<< ENDL。* / (q-- ) { (x)を読み出す;(y)を読み出します。 もし(x == y)は { プリント(zt.own [X] .ma());プット("" )。 続け; } zt.LCA(X、Y) 印刷(zt.tmp.ma());プット("" ); } 戻り 0 。 }