HDU - 5398 GCD 트리 LCT

5398 - HDU

전처리는에 LCT 유지 보수의 모든 순간에 걸쳐 최대 값을 유지한다.

의 #pragma GCC의 최적화 (2)
 의 #pragma GCC의 최적화 (3)
 의 #pragma (4) GCC의 최적화 
#INCLUDE <비트 / stdc ++. H>
 #DEFINE는 LL 긴 긴
 #DEFINE의 LD 긴 이중
 #DEFINE의 ULL 부호 긴 긴
 #DEFINE의 인터넷 제
 #DEFINE SE 제
 #DEFINE MK make_pair
 #DEFINE PLL 쌍 <LL, LL>
 #DEFINE의 PLI 쌍 <LL, INT>
 #DEFINE PII 쌍 <INT, INT>
 #DEFINE SZ (X) ((INT) x.size () )
 #DEFINE ALL (x)를 (x)를 .begin (), (X) .END ()
 #DEFINE FIO IOS :: sync_with_stdio (거짓); cin.tie (0); 사용

 네임 스페이스 표준; 

CONST의  INT N = 3e5 + (7) ;
CONST  INT INF = 0x3f3f3f3f ;
CONST LL = INF 0x3f3f3f3f3f3f3f3f ;
CONST  INT 개조 = 998,244,353 ;
CONST   EPS 1e- = 8 ;
CONST  이중 PI ACOS = (- 1 ); 

서식 < 클래스 T, 클래스 S> 인라인 공극 추가 (T & A, S의 b) {A = B +; 경우 (a> = 개조) A - = 개조} 
템플릿 <클래스 T, 클래스 S> 인라인 공극 부 (T & A, S의 b) {A - = B를; 경우 (A < 0 )은 + = 개조} 
템플릿 < 클래스 T, 클래스 S> 인라인 BOOL chkmax (T & A, S B)는 { 반환 은 <B를? A = B,  : 거짓 } 
템플릿 < 클래스 T, 클래스 S> 인라인 부울 chkmin (T & A, S의 b) { 반환 A> B를? A = B, 사실 : 거짓 ;} 

mt19937 RNG (크로노 :: steady_clock : 지금 () time_since_epoch () () 계산합니다.).

INT의 N; 
LL의 ANS [N]; 
지금 LL; 
INT의 어린 아이;
INT U [N] V [N]; 
벡터 < INT > FAC [N]; 

구조체 LCT {
 #DEFINE의 L (X) (CH [X] [0])
 #DEFINE의 R (X) (CH [X] [1])
     INT FA [N], CH [N] [ 2 ], REV [N , SZ [N], Q [N]; 
    PII MN [N], w [N]; 
    무효화 INIT ( INT의 N)를 {
         위해 ( int로 I = 0 ; I <= N이, 난 ++ ) { 
            FA [I] = REV [I] = 0 ; 
            SZ [I] = 1; 
            MN은 [I] 승 = [I] MK = ( 1000000 , I); 
            CH [I] [ 0 ] = CH의 [I] [ 1 ] = 0 ; 
        } 
        TOT = N + 1 ; 
    } 
    인라인 부울 isroot ( INT X) {
         복귀 L (FA [X) = X (R) && (FA [X]) =! (X); 
    } 
    인라인 공극 손잡이 ( INT의 X) { 
        SZ [X] = SZ [1- (X)] + SZ [R (X)] + 1 ; 
        MN이 [X] = w는 [X]; 
        chkmin (MN [X], MN [1- (X)]);
        chkmin (MN [X], MN [R (X)]);
    } 
    인라인 무효 푸시 ( INT의 X) {
         경우 (REV [X]) { 
            REV [X] = 0 ; 스왑 (L (X), R (X)); 
            REV [1- (X)] ^ = 1 ; REV [R (X)] ^ = 1 ; 
        } 
    } 
    인라인 공극 ROT ( INT의 X)를 {
         INT Y = FA [X] Z = FA [Y], L, R;
        경우 (CH [Y] [ 0 ] == X) L = 0 , R = L ^ 1 ;
         , L = 1, R = L ^ 1 ;
        만약 (! isroot (Y)) {
             경우 (L (z) ==의 Y) L (z) =의 X;
            다른 R (z) =의 X; 
        } 
        FA [X] = Z; FA [Y] = X를; FA [CH [X] [R] = Y; 
        CH [Y] [1] = ch를 [X] [R]; CH [X] [R]를 = Y를; 
        (Y) 풀; (x)를 당겨; 
    } 
    인라인 공극 스플레이 ( INT X) {
         INT의 상부 = 1 ; Q [맨] =의 X;
        위한 ( int로 된 I = X의 단계;! isroot의 (Ⅰ) 내가 FA = [I]) Q [++ 가기 = FA [I];
        ...에 대한( INT  가기 = 1을, 난, 난 -) 푸쉬 (Q [I]);
        반면 (! {isroot (X))
             INT Y = FA [X] Z = FA [Y];
            만약 (! {isroot (Y))
                 의 경우 ((L (Y) == X) ^ (L (z) == Y)), ROT (X);
                다른 ROT (Y); 
            } 
            ROT (X); 
        } 
    } 
    인라인 무효 액세스 ( INT의 X) {
          ( INT Y = 0 , X, Y = X, X = FA [X]) { 
            스플레이 (X); 
            R은 (X) = (Y)를;
            (x)를 당겨; 
        }
    } 
    인라인  Y) {공극 makeroot ( INT X) { 
        접속 (X); 스플레이 (X); 레브 [X] ^ = 1 ; 
    } 
    인라인 INT 이제 findroot ( INT X) { 
        접속 (X); 스플레이 (X); 
        반면 (L (X))의 X를 = L (X);
        반환 X를; 
    } 
    인라인 공간 분할 ( INT의 X, INT의 Y) { 
        makeroot (X); 액세스 (Y); 스플레이 (Y); 
    } 
    인라인 공극 링크 ( INT의 X, INT 
        makeroot (X) FA [X]= Y; 스플레이 (X); 
    } 
    인라인 보이드 컷 ( INT의 X, INT의 Y) { 
        분할 (X, Y); 
        경우 (L (Y) == X) L (Y) = 0 , FA는 [X] = 0 ; 
    } 
    공극 변화 ( INT의 X, INT의 Y, INT의 중량) {
         경우 (! 이제 findroot (X) = 이제 findroot (Y)) {
             ++의 TOT; 
            w [TOT] = MK (중량 TOT); 
            U [TOT] = X를; V [TOT는] = y로; 
            SZ [TOT는] ;= 1 개
            링크 (X, TOT); 
            링크 (Y, TOT); 
            지금 + = 중량;
            반환 ; 
        } 

        makeroot (X); 
        액세스 (Y); 
        스플레이 (Y); 
        PII MINVAL = MN [Y]; 

        경우 (minVal.fi> = 중량) ; 
        컷 (minVal.se, V [minVal.se]); 
        컷 (minVal.se, U [minVal.se]); 
        지금 - = minVal.fi; 

        w [minVal.se] = MK (중량 minVal.se); 
        U [minVal.se] = X를; V [minVal.se = Y; 
        SZ [minVal.se] = 1; 
        링크 (X, minVal.se); 
        링크 (Y, minVal.se); 
        지금 + = 중량; 
    } 
} LCT; 

INT 의 main () {
     위해 ( int로 I = 1 ; i가 <= 100000 ; I ++ ) {
         위해 ( INT의 J = 난 + I, J <= 100000 ; J + = I) { 
            FAC [J] .push_back (I); 
        } 
    } 

    lct.init ( 100,000 ); 

    위한 ( int로 I = 2 ; 나는 = < 100000 ; I ++) {
         ( INT의 J : FAC [I]) { 
            lct.change (I, J, J); 
        } 
        ANS [I] = 현재; 
    } 

    동안 (는 scanf ( " %의 D ' , N)! = EOF) { 
        의 printf ( " % LLD \ 없음 " , ANS [N]); 
    } 
    반환  0 ; 
}

 

추천

출처www.cnblogs.com/CJLHY/p/11274169.html