POJ 2104 간격 k 번째로 큰 나무 (회장)

주제 링크 : http://poj.org/problem?id=2104

타이틀 효과 :뿐만 아니라 주어진 N의 시퀀스 번호 m 조작, L, R, K를 포함하는 각 동작 구간 발견 [L을 R] k 번째로 큰

문제 해결 방안은 : 최대 세그먼트 트리는 최소 서열을 유지 트리 라인의 N 개의 포함 된 각 입력 시퀀스 접두어 세그먼트 트리의 구축을 고려할 수 있고, 이것은 확실히 메모리 버스트 것이다. 같은 나무의 두 인접 분절 사실, 아마 로그 n 개의 노드, 우리는 거기에 새 로그 n 개의 노드를 열어 다른 많은있다. 현재의 노드 번호의 각각의 합계가 저장된 노드 번호 우리 세그먼트 트리의 L-1 개를 얻는다 제 세그먼트 트리 감산을 사용하여 간격 [L, R, R 피스 [L, R] 간격으로 나타나는 각 노드가 자신의 좌측 서브 트리에서 시작하여 나타나는 횟수 이상인 K 왼쪽 서브 K에 큰 나무를 찾는 경우에, 좌측 서브 트리의 노드 번호 K에 동일 합보다 큰지 여부를 판단하거나 상기 제 우측 서브 트리를 찾는 검색 시작 케이 합 대형.

코드 :

사용법 #include <iostream> 
#INCLUDE <알고리즘> 
#INCLUDE <벡터> 
#INCLUDE <cstdio>
 사용  스페이스 성병;
CONST의  INT maxn 1E5 + = 6 ;
INT의 N, m, CNT 루트 [maxn], A [maxn, X, Y, K;
구조체 노드 {
     INT의 L, R, 합; 
} T [maxn * 40 ]; 
벡터 < INT > V;
INT getid ( INT X) {
     복귀 LOWER_BOUND (v.begin () v.end (), X) -v.begin () + 1 ; 
} 
무효 업데이트 ( INTL, INT R, INT 및 X, INT의 Y, INT의 POS) { 
    T [ ++ CNT = T [Y], T [CNT] .sum ++ 
    , X = CNT;
    경우 (L == R) ;
    int로 중간 = L + R >> 1 ;
    경우 (MID> = POS) 업데이트 (좌, 중, T [X] 펜닐, T [Y] 펜닐, POS);
    다른 업데이트 (MID + 1 , R, T [X] .R, T [Y] .R, POS); 
} 
INT의 쿼리 ( INT의 L, INT의 R, INT (X), INT의 Y, INT의 K) {
     경우 (L == R) 엘;
    int로 중간 = L + R >> 1 ;
    INT의 합 = T [T [Y] 펜닐] .sum- T [T [X] 펜닐] .sum;
    경우 (합계> = K) 리턴 질의 (좌, 중, T [X] 펜닐, T [Y] 펜닐, K);
    다른  리턴 질의 (MID + 1 , R, T [X] .R, T [Y] .R, K- 합); 
} 
INT 의 main () { 
    는 scanf ( " %의 D % d에 " , N, m);
    위한 ( int로 I = 1 ; 나는 <= N; ++ i가 ()는 scanf를 " 가 % d " , & A [I]) v.push_back (a [I]); 
    종류 (v.begin (), v.end ()), v.erase (독특한 (v.begin (), v.end ()), v.end ());
    위한 ( int로 I = 1 ; 나는 <= N; 내가 ++) 업데이트 ( 1 N, 루트 [I], 루트 [I- 1 ] getid (a [I]));
    위한 ( int로 난 = 1 난 ++; I <= m {) 
        는 scanf ( " % D % D % D ' , X, Y, K)을; 
        의 printf ( " % D \ 없음 " , V [질의 ( 1 N, 루트 [X- 1 ], 루트 [Y, K) - 1 ]); 
    } 
    반환  0 ; 
}

 

추천

출처www.cnblogs.com/zjl192628928/p/11230261.html