POJ-2299-울트라 이것은 QuickSort (단일 지점 업데이트 간격 + + 쿼리 이산)

이 문제에서는 특정 정렬 알고리즘을 분석해야한다. 알고리즘은 시퀀스는 오름차순으로 정렬 될 때까지 두 개의 인접한 시퀀스의 요소를 교환하여 N 개의 별개의 정수들의 시퀀스를 처리한다. 입력 시퀀스 
9 1 0 5 4

울트라 이것은 QuickSort는 출력을 생성 
0 1 4 5-9.

당신의 작업은 매우 이것은 QuickSort가 주어진 입력 순서를 정렬하기 위해 수행 할 필요가 얼마나 많은 스왑 작업을 결정하는 것입니다.

입력

입력은 여러 테스트 케이스가 포함되어 있습니다. 입력 시퀀스의 길이 - 모든 테스트 케이스는 하나의 정수 n <50을 포함하는 선으로 시작한다. 다음 상기 N 라인의 각각은 [I] ≤ 999,999,999, i 번째 입력 시퀀스 요소 ≤ 단일 정수 0을 포함한다. 입력은 길이 N의 시퀀스를 종료한다 = 0이 시퀀스가 ​​처리해서는 안된다.

산출

모든 입력 순서를 들어, 프로그램이 정수 연산을 포함하는 단일 행을 인쇄, 필요한 스왑 작업의 최소 수는 지정된 입력 순서를 정렬합니다.

샘플 입력

5 
9 
1 
0 
5 
4 
3 
1 
2 
3 
0

샘플 출력

6 
0
#INCLUDE <cstdio> 
#INCLUDE <iostream> 
#INCLUDE <CString을> 
#INCLUDE <알고리즘> 
#INCLUDE <큐> 
#INCLUDE <적층> 
#INCLUDE < 설정 > 
#INCLUDE <벡터> 
#INCLUDE <지도>
 CONST의  INT maxn = 5e5 + (5) ; 
타입 정의  LL;
사용하는  네임 스페이스 표준을;
구조체 노드 
{ 
    LL의 L, R; 
    LL 합계; 
} 트리 [maxn << 2 ];
int로 A [maxn, 서브 [maxn, 카본 나노 튜브를;

팔 굽혀 펴기 ( INT의 m) 
{ 
    트리 [m] .sum = (트리 [m << 1 ] + 트리 .sum [m << 1 | 1 ] .sum); 
} 
// 무효 푸시 (INT의 m)
 // {
 //     경우 (트리 [m] .lazy)
 //     {
 //         트리 [m << 1] = .lazy 트리 [m] .lazy;
//         트리 [m << 1 | 1] = .lazy 트리 [m] .lazy;
//         트리 [m << 1] = .sum 트리 [m]의 .lazy * (트리 [m << 1] .R 트리 [m << 1] 펜닐 + 1);
//         트리 [m << 1 | 1] = .sum 트리 [m]의 .lazy * (트리 [m << 1 | 1] .R 트리 [m << 1 | 1] 펜닐 + 1);
//         트리 [m] .lazy = 0; 
// } 
공극 빌드 ( INT의 m, INT의 L, INT의 R) 
{ 
    트리 [m] 펜닐 = L; 
    트리 [m] .R = R; 
    트리 [m] .sum = 0 ;
    경우 (L == R) 
    { 
        트리 [m] .sum = 0 ;
        반환 ; 
    } 
    INT 중간 = (트리 [m] + 트리 .L [m] .R) >> 1 ; 
    빌드 (m << 1 , L, MID); 
    구축 (m << 1 | 1 , 중반 + 1 , R);
    팔 굽혀 펴기 (m); 
    반환 ; 
} 
공극 업데이트 ( INT의 m, INT의 인덱스, INT의   발) 
{ 
    경우 (트리 [m] 펜닐 == 인덱스 && 트리 [m] 펜닐 == 트리 [m] .R) 
    { 
        트리 [m] .sum ++ ;
        반환 ; 
    } 
    INT 중간 = (트리 [m] + 트리 .L [m] .R) >> 1 ;
    경우 (인덱스 <= MID) 
    { 
        업데이트 (m << 1 인덱스, 발); 
    } 
    다른  
    { 
        업데이트 (m << 1 | 1인덱스, 발); 
    } 
    팔 굽혀 펴기 (m); 
    반환 ; 
} 
LL 쿼리 ( INT의 m, INT의 L, INT의 R) 
{ 
    경우 (L> R) 
    { 
         0 ; 
    } 
    경우 (트리 [m] 펜닐 == && 트리 L [m] == .R R) 
    { 
        복귀 트리 [m] .sum; 
    } 
//     푸시 (m); 
    INT 중간 = (트리 [m] + 트리 .L [m] .R) >> 1 ;
    경우 (R <= MID) 
    { 
        리턴 질의 (m << 1 , L, R); 
    } 
    다른 경우 (L> MID) 
    { 
        리턴 질의 (m << 1 | 1 , L, R); 
    } 
    다른 
    { 
        리턴 질의 (m << 1 , L, MID) + 쿼리 (m << 1 | 1 중간 + 1 , R); 
    } 
} 

INT 의 main () 
{ 
   INT의 N;
   반면 (CIN >> N) 
   { 
       경우 (N 개의 == 0 ) 
       { 
           중단 ; 
    } 
    에 대해 ( int로 I = 0 ; I <N은; I ++)는 scanf ( " % d의" , 서브 [I])와, [I]가 = 서브 [I]가, 
    정렬 방법 (이하, 서브 + N)    
     INT의 크기 = 고유 (이하, 서브 + N) - 부;   
     위해 ( int로 = 1을 0 ; 나는 < N; 내가 ++ ) 
    이 [I] = LOWER_BOUND (이하, 서브 + 사이즈, A [I]) - 서브 + 1 ] 
    구축 ( 1 , 1 , 크기), 
    LL 합 = 0 ;
      ( INT의 t = 0 ; t <N ; t ++ ) 
    { 
        합계 + = 쿼리 ( 1 , A [t] + 1 , 크기), 
        업데이트 (1 , A [t], 1 ); 
    } 
    의 printf ( " % LLD \ 없음 " , 합); 
    
   } 
   반환  0 ; 
}

 




추천

출처www.cnblogs.com/Staceyacm/p/11298857.html