問題の意味:n点があり、一方向のN-1辺、各ポイントは、商品を販売します
Qは、商品の種類yの第二種を購入し、ポイント1からxと商品の同じタイプを購入する最初のを歩き始めた、と異なる順序対<X、Y>番号を尋ね
ソリューション:
COL [i]は、この製品のタイプの点を表します
最後[COL [I]はIプロセスを指すように、時点1から父、品物の種類最後に現れる点Iを表します。
VIS [COL [I]は、プロセスから点I、点iの通過の製品タイプ番号を示し
NUM [I]は、点iと品の異なる種類の数からプロセスを表します
たびに新しいスイープ点v、(uとvの父)NUM [U] - NUM [最後の[COL [V]]]を更新する必要がありますの数です
#include <ビット/ STDC ++ H> 使用して 名前空間STDを、 typedefの長い 長いLL。 const int型の M = 1E5 + 10 。 const int型 MOD = 1E9 + 7 。 INT NUM [M]、VIS [M]、ANSS [M]、ANS、CNT、COL [M]、ヘッド[M]、最後に[M]。 構造体ノード{ int型に、次。 }エッジ[M]。 ボイド add_edge(INT U、INT V){ エッジ[ ++ CNT] .next = 頭部[U]。 エッジ[CNT] .TO = V。 ヘッド[U] = CNT。 } ボイド DFS(INT U、int型の和、INT ANS){ ため(INT iはヘッド= [U]; iは、iが= エッジを[I] .next){ int型 V = エッジ[I] .TO。 int型、T = 0 ; int型 lastt = 最後の[COL [V]]; VIS [COL [V]] ++ ; もし(VIS [COL [V]] == 1)NUM [V] = NUM [U] + 1 。 他 NUM [V] = NUM [U]; T = NUM [U] - NUM [最後[COL [V]]]。 最後に[COL [V]] =U; // のprintf( "%D%D%D \ n"は、V、COL [V]、最後[COL [V])。 ANSS [V] = ANS + T。 もし(VIS [COL [V]] == 1)DFS(V、和+ 1、ANS + T)。 他の DFS(V、合計+ 1、ANS + T)。 VIS [COL [V]] - 。 最後[COL [V] = lastt。 } } int型のmain(){ int型のn; 一方、(〜のscanf(" %d個"、&N)){ CNT = 0 。 のmemset(ヘッド、0、はsizeof (ヘッド))。 以下のために(INT iが= 1 ; <I = N; I ++)NUM [I] = 0、最後の[I] = 0、VIS [I] = 0、ANSS [I] = 0 ; 以下のために(INT iが= 2 ; I <= N; I ++ ){ int型、U。 scanf関数(" %のD "、&U)。 add_edge(U、I); } ため(INT iは= 1 ; iが<= N; I ++ ) のscanf(" %dの "、&COL [I])。 VIS [COL [ 1 ]] ++ ; NUM [ 1 ] = 1 。 DFS(1、1、0 ); // ため(; <I = N;整数iが1 = I ++){ // のprintf( "%dの"、NUM [I])。 // } // のprintf( "\ n"); 以下のために(INT iが= 2 ; I <= N; I ++ ){ のprintf(" %D \ n " 、ANSS [I])。 } } 戻り 0 。 } / * 3 1 2 1 2 3 3 1 1 1 2 3 4 1 2 3 1 3 2 3 7 1 1 3 2 4 2 3 3 3 4 5 3 3 7 1 1 3 2 4 2 2 3 3 4 5 3 3 * /