항목 링크 : HTTPS : //vjudge.net/problem/POJ-3162
나무에 최대 거리를 찾는 트리의 각 노드는,이 [I]로 지칭하고 만족하는 범위로 최대의 최대 간격 [L, R (A [I]) 비교 - (분 : 질문 의도 A [I]) <= M.
아이디어 : 첫 번째 단계는 가장 긴 거리의 각 노드에 대해 계산 같은 문제 트리 DP, 나는 다른 블로그 게시물 https://www.cnblogs.com/FrankChen831X/p/11375572 쓴 것을 hdoj2196합니다. HTML. 최대 거리 A [I]을 얻은 후, 최소 및 최대 세그먼트 트리 유지 보수주기를 확립한다. 그때, J 다시 이송 두 포인터는마다 [I, J] 대답 갱신 최대 및 최소 ans1의 ANS2, 얻어이므로하지 모든 J 초기화, O (nlogn)의 전체 복잡성.
AC 코드 :
#INCLUDE <cstdio> #INCLUDE <알고리즘> 사용 스페이스 성병; 타입 정의 긴 긴 LL; CONST의 INT maxn 1E6 + = 5 ; CONST LL = INF 0x3f3f3f3f3f3f3f3f ; INT의 N, ANS, CNT, 헤드 [maxn, PT [maxn], A [maxn]; LL M, DP [maxn] [ 3 ], ans1, ans2; 구조체 노드 1 { INT의 V, NEX; LL의 w; } 에지 [maxn << 1 ]; 구조체 노드 2 { INT의 L, R; LL 최대, 최소, } TR [maxn << 2 ]; 보이드 adde ( int로 U, INT의 V, LL의 w) { 에지 [ ++ CNT] .V = V; 에지 [CNT] .W = w; 에지 [CNT] .nex = 헤드 [U]; 헤드 [U] = CNT; } 공극 dfs1 ( int로 U, INT의 FA) { 위해 ( int로 I = 헤드 [유] I, I = 가장자리 [I]를 .nex) { INT의 V = 에지 [I] .V; w LL = 가장자리 [I] .W; 경우 (V == FA가) 계속 ; dfs1 (V U, 께); 만약 (w + DP [V] [ 0] "DP는 [U]를 [ 0 ]) { DP가 [u는 [ 1 ]을 DP = [U] [ 0 ]; DP는 [U]는 [ 0 ] + DP 승 = [V] [ 0 ]; PT [U] = V; } 다른 경우 (w + DP [V] [ 0 ] "DP [U] [ 1 ]) DP [U] [ 1 ] = w + DP [V] [ 0 ]; } } 공극 DFS2을 ( int로 U, INT의 FA) { 위해 ( int로 I = 헤드 [유] I, I = 가장자리 [I]를 .nex) { INT의 V = 에지 [I] .V; w LL= 가장자리 [I] .W; 경우 (V == FA가) 계속 ; 경우 (! V = PT [U]) DP는 [V] [ 2 ] + W 최대 = (DP [U] [ 0 ], DP [U] [ 2 ]); 다른 DP는 [V] [ 2 ] + W 최대 = (DP [U] [ 1 ], DP [U] [ 2 ]); DFS2 (V U, 께); } } 공극 팔 굽혀 펴기 ( INT의 V) { TR [V] .Max = 최대 (TR [V << 1 ] .Max, TR [V << 1 | 1 ] .Max); TR [V] 30 ℃와 pH 5.5 또는 다른 pH = 분 (TR의 [V의 << 1] 30 ℃와 pH 5.5 또는 다른 pH, TR [V << 1 | 1 ] 30 ℃와 pH 5.5 또는 다른 pH); } 공극 빌드 ( INT의 V, INT의 L, INT의 R) { TR [V] 펜닐 = 1, TR [V] .R = R; 경우 (L == R)은 { TR은 [V] .Max = TR은 [V]는 30 ℃와 pH 5.5 또는 다른 pH = A [L]을; 반환 ; } INT 중간 = (L + R) >> 1 ; 빌드 (V << 1 , L, MID); 구축 (V << 1 | 1 , 중반 + 1 , R); 팔 굽혀 펴기 (V); } 무효 쿼리 ( INT V,INT의 L, INT의 R) { 경우 (L <= TR [V] 펜닐 && R> = TR [V] .R) { ans1 = 최대 (ans1, TR [V] .Max); ans2 = 분 (ans2, TR [V] 30 ℃와 pH 5.5 또는 다른 pH); 반환 ; } INT 중간 = (TR [V] 펜닐 TR + [V] .R) >> 1 ; 경우 (L <= MID) 쿼리 (V << 1 , L, R); 경우 (V << (R> MID) 질의 1 | 1 ], L, R) } INT 의 main () { 는 scanf ( " % d 개 %의 LLD " , N, M); 대 ( INT I = 2; 나는 = <N; ++ I) { INT의 V; LL의 w; scanf와 ( " % d 개 %의 LLD ' , V, W); adde (I, V, W); adde (V, I, w); } dfs1 ( 1 , 0 ); DFS2 ( 1 , 0 ); 위한 ( int로 I = 1 ; i가 <= N; ++ I) 이 [I] = 최대 (DP [I] [ 0 ], DP [I] [ 2 ]); 구축 ( 1 , 1 , N); INT의 J = 1 ; 대한 (int로 I = 1 ; 나는 <= N; ++ I) { 동안 (j <= N) { ans1 = 0 , ans2 = INF; 쿼리 ( 1 , I, J); 경우 (ans1 ans2 -> M) 분해 ; ++ J; } ANS = 최대 (ANS, J = I); } 의 printf ( " % D \ 없음 " , ANS); 반환 0 ; }