実際には、このトピックには、それをこすり、長い間行われてきたが、急に行われないことが判明GZOI
質問の意味:与えられたの$ X、Yの$需要
$$ \ sum_ DEP(LCA(I、Y)){iは当量xを\} ^ K $$
まずは、このトピックの簡易版を見てみましょう
https://www.luogu.org/problem/P4211
求$$ \ sum_ DEP(LCA(I、Y)){iは当量xを\} $$
のは、実際の意味の$ DEPの$を見てみましょう - i点から(I含め)どのように多くのポイントのルートに。
ルートへのパス上の$ yを$のすべての$ LCAの$:私たちは、発見を求めて、全体として考えます。だから、深さの多くが$ LCAの$寄与を持っていることをいくつかのポイントがあり、この寄付は、$ LCAの$以下この時点で数に等しいので、我々はルートへのパス上のすべての$ LCAの$それぞれを置くことができます重みポイントがプラスされています。そして、統計的重みに沿って、上向きの$のy $からルートに行ってきましたが答えです。
ここでは、私たちがペイントされた、各ノードは、上記の点のすべてをジャンプします$ xには$の並べ替えに合わせて、すべてのオフラインの問い合わせを置くことができ、その後、クエリ時間しかあり塗られたどのように多くのノードを見るために見つける必要がありますそして、貢献を計算し、ここで我々は唯一の行に分割されたツリーのチェーンを維持する必要があります
そして、私は非常に醜いコードでした
#include <ビット/ STDC ++ H> 名前空間STDを使用して、 #defineレジスタ再度 の#defineっ長い長 の#defineのGC GETCHAR() インラインLLリード() { チャーC再(GC); LL X再(0)、F(1)。 一方、(C> '9' || C < '0')、F = C == ' - ' - 1:1、C = GC;? 一方(> = '0' && C C <= '9')、X = X * 10 + C-48、C = GC。 F * xを返します。 } CONST LL N = 50500、MOD = 201314。 LLのN、Q、K、H [N]、CNT、QS。 構造体縁{に、次っ;} E [N]。 ボイド追加(LL U、V LL){E [++ CNT] =(エッジ){H [U]、V}、H [U] = CNT;} (LL I = hのための#define QXX(U)[ U]、V; V = E [i]は.TO、I; I = E [I] .next) LL DEP [N]、FA [N]、息子[N]、SIZ [N]、トップ[N] 、REV [N]、配列[N]、TOT。 ボイドDFS(LL U) { SIZ [U] = 1。 SIZ [U] + = SIZ [V]。 IF(SIZ [息子[U] <SIZ [V]) 息子[U] = V。 } } ボイドのDFS(LL U) { IF(息子[U]) { LLのV =息子[U]。 配列[V] = ++ TOT。 REV [TOT = V。 トップ[V] = TOP [U]。 DFS(V); } QXX(U) { IF(V ==息子[U])続けます。 配列[V] = ++ TOT。 REV [TOT = V。 トップ[V] = V。 DFS(V); } } 構造体ノード{LLのID、X、Z、ANS; W BOOL; Q} [N << 1]。 ブール演算子<(ノードA、ノードB){戻りAX <BX;} の#define LS番号<< 1つ の#define RS番号<< 1 | 1台 の#define半ば((L + R)>> 1) LL和[N << 2]、タグ[N << 2]。 ボイド押し上げ(LLのID){和[ID] =(和[LS] +和[RS])%のMOD;} ボイドプッシュダウン(LLのID、LLのL、LLのR) { IF(タグ[ID]) { タグ[LS] + =タグ[ID]。 タグ[RS] + =タグ[ID]。 和[LS] + =タグ[ID] *(MID-L + 1)。 和[RS] + =タグ[ID] *(R-MID)。 和[LS]%= MOD。 和[RS]%= MOD。 タグ[ID] = 0; } } ボイド変化(LLのID、LLのL、R -1,11,11-のL、LL R) { (Lは> = L && R <= R)であれば { タグ[ID] ++; 和[ID] + =(R-L + 1)。 和[ID]%= MOD。 返します。 } プッシュダウン(ID、L、R)。 IF(中間> = L)の変化(LS、L、中、L、R)。 IF(中間<R)変化(RS、ミッド+ 1、R、L、R)。 突き上げ(ID)。 } ボイドワーク(LL x)から { (1)一方 { (!トップ[X] = X)であれば 変化(1,1、TOT、配列[トップ[X]、配列[X])、X = FA [TOP [X]]。 他 { 変化(1,1、TOT、配列[x]は、配列[X])。 X = FA [X]。 } (x == 0)戻った場合、 } } LLクエリ(LLのID、LLのL、R -1,11,11-のL、LL R) { IF(L> = L && R <= R)戻り和[ID]%MOD。 プッシュダウン(ID、L、R)。 LL ANS = 0。 IF(中間> = L)ANS + =クエリ(LS、L、中、L、R)。 IF(中間<R)ANS + =クエリ(RS、ミッド+ 1、R、L、R)。 ANS%MODを返します。 } (LLのX)を尋ねるでしょ { LL ANS = 0。 一方、(1) { IF(TOP [X] = X!) ANS + =クエリ(1,1、TOT、配列[トップ[X]、配列[X])、X = FA [TOP [X]]。 他 { ANS + =クエリ(1,1、TOT、配列[x]は、配列[X])。 X = FA [X]。 } ANS%= MOD。 (x == 0)戻りANS場合、 } } LL ANS [N]。 メインINT() { N =(読み取り)、Q =読み取り()。 以下のために(LL I = 2; iが<= N; ++ I) { LL X =リード()+ 1。 (X、i)を追加します。 FA [I] = xと; } トップ[1] = 1;配列[1] = ++ TOT。 DFS(1)のDFS(1)。 用(LL I = 1; I <= Q; ++ I) { LL 1 =読み取り()、R =リード()+ 1、zが読み取り=()+ 1。 Q [++ QS =(ノード){I、L、Z、0,0}; Q [++ QS =(ノード){I、R、Z、0,1}; } ソート(Q + 1、QS + 1 + Q)。 LL T = 0。 一方、(Q [T + 1] .X <1)++ T。 (LL I = 1 ++ I; iが<= N)のための { 作業(I)。 一方(Q [T + 1] .X <= I && T <QS) (Q [t]と尋ねる= ++ T、Q [t]は.ans .Z); IF(Tの==適量)破ります。 } のための(LL I = 1; I <= QS; ++ I) { (Q [i]が.W == 0)ANS場合[Qを[I] .ID] - = Q [i]は.ans。 他ANS [Q [I] .ID] + = Q [i]は.ans。 } (LL i = 1; I <= Q; ++ i)に対する COUT <<(ANS [i]が+ MOD)%のMOD << ENDL。 0を返します。 }
その後、我々はここでは$ K $番目以上で、この質問に戻ります
$ kを$にし、我々のインデックス、だからここ> DEP [I + 1] $実際に違いをしている - 彼らは$のDEPどこから来まず、[i]は、それぞれ$ 1 + $の前で見て
$のDEP [i]は^ K - >(DEP [i]が1)^ k個の$
そこで、我々はその後、各ノードのそれぞれの$ DEP ^ k個の$のための$ DEPを増加させる時間に相当されてアウトを事前に[X] $の^ K-(DEP [X] -1)^貢献
その後、我々は、$ B $は一定値が、各ノードで同じでない場合シーケンスについて、各点の値は、$ * Bが$であり、各動作が間隔を変更するためになさプラス$ A $さ、に変換することができます1との間隔クエリ
その後、我々は木のラインにそれ上の$ sum_b $を維持するために多くの時間を維持します
#include <ビット/ STDC ++ H> 名前空間STDを使用して、 #defineレジスタ再度 の#defineっ長い長 の#defineのGC GETCHAR() インラインLLリード() { チャーC再(GC); LL X再(0)、F(1)。 一方、(C> '9' || C < '0')、F = C == ' - ' - 1:1、C = GC;? 一方(> = '0' && C C <= '9')、X = X * 10 + C-48、C = GC。 F * xを返します。 } CONST LL N = 50050、MOD = 998244353。 LLのN、Q、K、H [N]、CNT、QS。 構造体縁{に、次っ;} E [N]。 ボイド追加(LL U、V LL){E [++ CNT] =(エッジ){H [U]、V}、H [U] = CNT;} (LL I = hのための#define QXX(U)[ U]、V; V = E [i]は.TO、I; I = E [I] .next) LL DEP [N]、FA [N]、息子[N]、SIZ [N]、トップ[N] 、配列[N]、REV [N]、TOT。 ボイドDFS(LL U) { SIZ [U] = 1。 DEP [U] +1 = [V] DEP。 DFS(V); SIZ [U] + = SIZ [V]。 IF(SIZ [息子[U] <SIZ [V]) 息子[U] = V。 } } ボイドのDFS(U -1,11,11-に) { SEQ [U] = ++ TOT、REV [TOT = U。 トップ[U] =であり; IF(息子[U]) のDFS(息子[U]、トップ[U])。 QXX(U) { IF(V ==息子[U])続けます。 DFS(V、V); } } LL qpow(LLのX、LL b)は { = 1 LL。 一方、(B) { IF(B&1)A =(X * A)%MOD。 X =(X * X)%のMOD、B >> = 1。 } を返します。 } の#define LS番号<< 1つ の#define RS番号<< 1 | 1台 の#define半ば((L + R)>> 1) LL SU [N << 2]、合計[N << 2]、タグ[N << 2]、PO [N]。 ボイド押し上げ(LLのID) { 和[ID] =和[LS] +和[RS]。 SU [ID] = SU [LS] + SU [RS]。 } ボイドプッシュダウン(LLのID、LLのL、LLのR) { IF(タグ[ID]) { タグ[LS] + =タグ[ID]。 タグ[RS] + =タグ[ID]。 和[LS] =(和[LS] +タグ[ID] * SU [LS])%MOD。 和[RS] =(和[RS] +タグ[ID] * SU [RS])%MOD。 タグ[ID] = 0; } } ボイド内蔵(LLのID、LLのL、LLのR) { IF(L == R) { SU [ID] =(PO [DEP [REV [L]]] + MOD-PO [DEP [REV [L] ] -1])%のMOD。 返します。 } 組み込み(LS、L、MID)。 内蔵(RS、ミッド+ 1、R)。 突き上げ(ID)。 } 空隙変化(LLのID、LLのL、LL R、LLのL、LLのR) { IF(L> = L && R <= R) { タグ[ID] ++; 和[ID] + = SU [ID]。 和[ID]%= MOD。 返します。 } プッシュダウン(ID、L、R)。 IF(中間> = L)の変化(LS、L、中、L、R)。 IF(中間<R)変化(RS、ミッド+ 1、R、L、R)。 突き上げ(ID)。 } LLクエリ(LLのID、LLのL、R -1,11,11-のL、LL R) { IF(L> = L && R <= R)戻り和[ID]%MOD。 プッシュダウン(ID、L、R)。 LL ANS = 0。 IF(中間> = L)ANS + =クエリ(LS、L、中、L、R)。 IF(中間<R)ANS + =クエリ(RS、ミッド+ 1、R、L、R)。 ANS%MODを返します。 } ボイドワーク(LLのX) { ながら(1) { IF(TOP [X]!= X) 変化(1,1、TOT、配列[トップ[X]、配列[X])、X = FA [TOP [X]]。 他 { 変化(1,1、TOT、配列[x]は、配列[X])。 X = FA [X]。 } (x == 0)戻った場合、 } } (LLのX)を尋ねるでしょ { LL ANS = 0。 一方、(1) { IF(TOP [X] = X!) ANS + =クエリ(1,1、TOT、配列[トップ[X]、配列[X])、X = FA [TOP [X]]。 他 { ANS + =クエリ(1,1、TOT、配列[x]は、配列[X])。 X = FA [X]。 } ANS%= MOD。 (x == 0)戻りANS場合、 } } 構造体ノード{LLのID、X、Y、ANS;} Q [N]。 ブールcmpx(ノードA、ノードB){戻りAX <BX;} BOOL CMPI(ノードA、ノードB){b.id <a.id返します;} (INTメイン) { 用(LL I = 1; I <= Q; ++ I) N = read()は、Q =リード()、k)は、(読み取り=。 (LL I = 1 ++ I; iが<= n)のための PO [I] = qpow(I、K)。 用(LL I = 2; iが<= N; ++ I) { FA [i]を読み出します=(); 追加(FA [i]は、I)。 } DEP [1] = 1。 DFS(1)と、DFS(1,1)。 (1,1、TOT)内蔵。 用(LL I = 1; I <= Q; ++ I) { LL X =リード()、yが読み出さ=(); Q [I] =(ノード){I、X、Y、0}。 } ソート(Q + 1、Q + 1 + Q、cmpx)。 LL T = 0。 一方、(Q [T + 1] .X <1)++ T。 (; iは<= N ++ I LL I = 1)のための { 作業(I)。 一方、(Q [T + 1] .X <= I && T <Q) ++ T、Q [T] .ans =(Q [T] .Y)を尋ねます。 (T == Q)ブレークであれば、 } ソート(Q + 1、Q + 1 + Q、CMPI)。 0を返します。 COUT << Q [i]は.ans << ENDL。 }