poj3162 (DP + 세그먼트 트리 트리 최대 및 최소를 추구)

항목 링크 : 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 ; 
}

 

추천

출처www.cnblogs.com/FrankChen831X/p/11423208.html