トピックへのリンク:https://www.lydsy.com/JudgeOnline/problem.php?id=3631
タイトル効果:意味から、n個の頂点を持つ所与のツリーは、所定の配列順序のツリー全体は、[1]、[2]、[3] ... [n]がAを走行[1] [2]点を追加する必要が後に[3]、[N]に来るまで、ポイント右に行ってから、[2]、及び、各出力点の最終重量を指すようにしてください。
問題解決のアイデアは:まず、我々はそれがt sから来ると仮定すると、ケースを議論するために時間がかかる、私たちが作ることができるANS [S] ++、ANS [T] ++、ANS [LCA(S、T)] - 、およびLCA sおよびtの父マイナス1せ、最後に押され、一度歩いてn番目のノードへの第2のノード、及びそれがいずれかを減算します。
コード:
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 typedefの長い 長いLL。 const int型 MAXN = 300000 + 7 。 int型 N、TOT、[MAXN]、ヘッド[MAXN]、FA [MAXN] [ 25 ]、深さ[MAXN]は、[MAXN] ANS。 構造体のエッジ{ int型V、次。 }エッジ[MAXN * 2 ]。 ボイド追加(INT U、INT V){ エッジ[TOT] .V = V。 エッジ【TOT] .next = 頭部[U]。 ヘッド[U]は ++ TOTを= 。 } ボイド DFS(INT U、INT PRE){ 深[U] =深さ[事前] + 1 。 FA [U] [ 0 ] = 予備。 以下のために(int型 i = 1 ; iは<= 20 ; iは++ ) FA [U] [I] = FA [FA [U] [I- 1 ]] [I- 1 ]。 以下のために(int型 - ;!I = I =ヘッド[U] 1 ; I = {エッジ[I] .next) のint V = エッジ[I] .V。 もし(V ==前)続けます。 DFS(V、U); } } INT LCA(INT U、INT V){ 場合(深さ[U] < 深さ[V])スワップ(U、V)。 以下のために(int型 iは= 20、I> = 0 ; i-- ){ 場合(深さ[U] - (1 << I)> =深さ[V])U = FA [U] [I]。 } 場合(uが== v)を返すUと、 以下のために(int型 = Iを20 ; I> = 0 ; i-- ){ 場合(!FA [U] [I] = FA [V] [i])とU = FA [U] [i]は、V = FA [ V] [i]は、 } 戻り FA [U]を[ 0 ]。 } ボイド DFS1(INT U、INT PRE){ ため(int型 I =ヘッド[U]; I =! - 1 ; I = エッジ[I] .next){ int型 V = エッジ[I] .Vと、 もし(V ==前)続けます。 DFS1(V、U); ANS [U] + = ANS [V]。 } } int型のmain(){ scanf関数(" %のD "、&N) 以下のために(int型私= 1 ; iが<= N; iが++)のscanf(" %dの"、および[I])。 memsetの(頭、- 1、はsizeof (ヘッド))。 以下のために(int型 i = 1 ; iがn <; iは++ ){ int型Uを、V。 scanf関数(" %d個の%d個"、&U&V); (V、U)を追加します。(V、U)を追加。 } 深さ[ 0 ] = - 1 。 DFS(1、0 ); 以下のために(int型 I = 1 iは++; iがn < {) ANS [I]] ++ ; ANS [[I + 1 ] ++ ; INTの LCA = LCA([I]、[I + 1 ])。 ANS [FA [LCA] [ 0 ]] - 。 ANS [LCA] - 。 } DFS1(1、0 ); 以下のために(int型 I = 2 ANS [I]]; iが++; iが<= N) - 。 以下のために(int型 i = 1 ; iが<= N; iは++ ) のprintf(" %Dを\ n " 、ANS [I])。 リターン 0 ; }