Luogu_P4556 비 테일 [설명] 트리 차 트리 세그먼트 합병

질문은 표면 : https://www.luogu.com.cn/problem/P4556

(X, Y) Z 플러스 1의 경로.

나무는 차이가있을 수 있습니다.

X 및 Y는 증가된다. LCA는 마이너스 1을 뺀 1 LCA는 아버지입니다.

그러나 많은 다른 종류가 있기 때문이다.

각 점은 트리 라인을 유지하는 데 필요한.

합병의 어떤 종류의 최대를 추구 할 때.

마지막으로, 통계 대답은 DFS.

아이디어 간단한, 주요 코드는 깁니다. 

다음과 같이 코드입니다 :

의 #pragma -GCC - 최적화 ( "O2, Ofast 인라인, 풀다 - 모든 루프 -ffast-수학")
 의 #pragma -GCC - 대상 ( "AVX, SSE2, SSE3, SSE4, popcnt") 
#INCLUDE <비트 / stdc ++ H>.
 하여  스페이스 성병;
 CONST의  INT maxn = 100010 ;
 INT의 TT, N, m,
 구조체 노드 {
     INT의 NXT에,
     #DEFINE의 NXT (x)는 E [X] .nxt
     #DEFINE (X) 내지 E [X ] .TO 
} E [maxn << 1 ]
 의 INT 헤드 [maxn, TOT, DEP [maxn], [maxn [F 21 ] RT [maxn, NUM (CNT), X [maxn], Y [maxn ] Z [maxn, 발은 [maxn]는 [maxn] ans와; 
인라인 무효(ADD INT (X), INT의 Y) { 
    (에 ++ 등록 무비) = Y를; 
    NXT (TOT) = 헤드 [X] 헤드 [X]는 = TOT 단계; 
}  < INT > Q 단계; 
인라인 () {판독
      X = 0 , F = 1 ;  C = getchar가 ();
    반면 (c> ' 9 ' || C < ' 0 ' ) { 경우 (c == ' - ' ) F * = - 1 ; C = getchar가 ();}
     동안 (c> =' 0 ' && C <= ' 9 ' ) (X) = (X) * 10 + C- ' 0 ' , C = getchar가 ();
    반환 의 X *의 F 단계; 
} 
인라인 공극 BFS () { 
    q.push ( 1 ) 증착은 [ 1 ] = 1 ;
    반면 (q.size ()) {
         INT (X) = q.front (); q.pop ();
        위한 ( int로 I = 헤드 [X] I, I = NXT (I)) {
             INT = 행 에 (I);
            경우 ([을] DEP) 계속 ;
            DEP [을]가 = DEP [X] + 1 ; 
            F [발] 0 =의 X;
             ( INT의 J = 1 J ++; J <= TT ) 
                F [을] [J] F = [F [을] [J = 1 ] [J = 1 ]; 
            (행) q.push; 
        } 
    } 
} 
인라인 INT의 LCA ( INT의 X, INT의 Y) {
     경우 DEP ([X]> 출발 [Y]) 스왑 (X, Y);
    위한 ( int로 난을 TT =; I> = 0 ; 난 ... )
         만약DEP ([F [Y] [I]]> = DEP [X]) Y = F [Y] [I];
    경우 (X == y)를 반환 X;
    위한 ( int로 = TT를 I 단계; I> = 0 ; 난 ... )
         의 경우 (! F [X] [I] = F [Y] [I]), X = F [X] [I], Y = Y [F ][나는];
    반환 f를 [X] [ 0 ] 
} 
구조체 나무 {
     INT의 LC, RC, DT, TG; 
t} [maxn * 80 ];
보이드 인서트 ( INT의 P, INT의 L, INT의 R, INT의 VL, INT의 d) {
     경우 (L의 == 된 R) {
        t [P] .dt+ = D; 
        t [P] .tg = t [P] .dt? L : 0 ;
        반환 ; 
    } 
    INT 중간 = (L + R) >> 1 ;
     경우 (VL <= MID) {
          경우 (t [P] .lc!의) t [P] = .lc ++ NUM; 
         (t [P] .lc, L, 중, VL, D)를 삽입; 
     } 다른 {
          경우 (t [P] .RC!의) t [P] = .RC ++ NUM; 
         삽입 (t [P] .RC 중간 + 1 , R, VL, d); 
     } 
     t [P] .dt = 최대 (t [t [P] .lc] .dt, t [t [P] .RC] .dt); 
     t [P] .tg = t [t의 [피] .lc]> = t .dt [t [P] .RC] .dt?t [t [P] .lc] .tg : t [t의 [피] .RC] .tg; 
} 
INT의 병합 ( INT의 P, INT의 Q, INT의 L, INT의 R) {
     경우 (! 피) 리턴 큐;
    만약 (! Q) 반환 피;
    경우 (L == R) { 
        t [P] .dt + = t [Q] .dt; 
        t [P] .tg = t [P] .dt? L : 0 ;
        반환 P는; 
    } 
    INT 중간 = (L + R) >> 1 ; 
    t [P] .lc = 병합 (t [P] .lc, t [Q] .lc, L, MID); 
    t [P] .RC = 병합 (t [P] .RC, t [Q] .RC 중간 +1 , R); 
    t [P] .dt = 최대 (t [t [P] .lc] .dt, t [t [P] .RC] .dt); 
    t [P] .tg = t [t의 [피] .lc]> = t .dt [t [P] .RC] .dt? t [t [P] .lc] .tg : t [t의 [피] .RC] .tg;
    반환 P는; 
} 
공극 DFS ( INT의 X) {
     위해 ( int로 I = 헤드 [X] I, I = NXT (I)) {
         INT = 행 (I)에;
        경우 ([을] DEP <= [X] DEP) 계속 ; 
        DFS (행); 
        RT는 [X] = 병합 (RT [X], RT [행] 1 CNT); 
    } 
    ANS [X] =를 t [RT의 [X] TG.; 
} 
INT  ) (메인
{ 
    N = () m 읽기 ) (판독; 
    TT = ( INT ) (로그 (N) / 로그 ( 2 )) + 1 ;
    위한 ( int로 I = 1 ; i가 N이 <I ++ ) {
         INT X, Y는, X = 읽기 (); Y가 = 판독 (); 
        (x, y)를 추가, 부가 (Y, X); 
    } 
    BFS (); 
    위한 ( int로 I = 1 ; i가 <= N; 내가 ++)을 RT [I] = ++ NUM;
    위한 ( int로 I = 1 ; I <= m; 내가 ++ ) { 
        X는 [i]를 판독 = (), Y [I]를 판독 = (), Z [I] = 판독 (); 
        발 [I] =Z [I]; 
    } 
    정렬 (브로 + 1 , 발은 + 1 + m); 
    CNT는 고유 = (브로 + 1 , 발 + 1 + m) -val- 1 ;
    위한 ( int로 I = 1 ; I <= m; 내가 ++ ) {
         INT (X) = X [i]를, Y = Y [I];
        INT Z = LOWER_BOUND (브로 + 1 , 발 + 1 + CNT, Z [I]) - 브로;
        INT LC = LCA (X, Y); 
        삽입 (RT [X] 1 , CNT, Z, 1 ); 
        삽입 (RT의 [y를, (1) , 탄소 나노 튜브 (CNT), Z, 1 ); 
        삽입 (RT의 [LC의, 1 , 탄소 나노 튜브 (CNT), (Z) - 1 );
        경우 ([LC]는 [F 0 ])를 삽입 (RT [F [LC] [ 0 ], (1) , 탄소 나노 튜브 (CNT), (Z) - 1 ); 
    } 
    DFS ( 1 );
    위한 ( int로 I = 1 ; 나는 <= N; ++ i가 ()에서 printf " % D \ 없음 " , 발 [ANS [I])를;
    반환  0 ; 
}

 

추천

출처www.cnblogs.com/ChrisKKK/p/11544029.html