사전 지식 : 안티 - 분석 소수의 수
아이디어 : 안티 - 소수 후 솔루션은 세그먼트 트리 것입니다 함께.
제거 할 수 있고, 사람이 제거되지 않은 우리는 트리 유지 보수의 위치와 라인 밖으로되지 않은 사람의 위치를 제거.
우리는 아는 사람들의 분포를 A와 표현 모두 넣어 [1, n]은 범위, 인권이 제거되지 않은 한 후 유지 보수 간격 및 트리 라인으로, 그것을 제거 할 수는 없습니다, 트리 [루트] .value 총 수입니다. 는 x 번째 위치에있는 사람들 중, 우리가 범위를 찾을 수와 위치가 사람의 위치를 얻기 위해 X 경우 트리 라인의 진 본성,이 위치에 대한 권리는 0 값을 갱신하고 있기 때문에 다음, 그것을 트리 라인을 업데이트 이 사람들이 탈락했다 나타낼 수, 총 수는 마이너스 1, 그것은 게임에 남아 있습니다 얼마나 많은 사람들이 나타낼 수 있습니다.
이 사람의 어긋난 것을 가정하면 INX,있는 사람의 다음 밖으로 그의 왼쪽 (오른쪽) A-일, 우리는 모드 = A % (나머지 번호), 우리는 숫자 왼쪽 INX (L)과 오른쪽을 얻을 수 있습니다 (R)은 다음과 개별적인 개조 부호에 기초하여 다음의 위치를 결정한다.
1 #INCLUDE <iostream> 2 #INCLUDE <cmath> 3 #INCLUDE <cstdio> 4 5 #DEFINE LL 긴 길이 6 7 이용한 스페이스 성병; 8 9 CONST의 INT N = 5e5 + (10) ; 10 구조체 정보 { 11 숯 이름 [ 20 ]; 12 INT 차례; 13 } P [N]; 14 구조체 노드 { 15 INT의 L, R, 값; 16 INT 중반 () { 반환(L +의 연구) >> 1 ; } 17 } 트리 [N << 2 ]; 18 INT의 C [N]; 19 INT N, S, SS, INX; 20 INT PR [] = { 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 29 }; 21 INT 맥스 NUM; 22 23 공극 DFS ( INT의 INX, INT V, INT의 CNT, INT PW) { 24 위한 ( INT 난 = 1 ; I <= PW; ++ I) { 25 일 경우 ((LL) V * PR [INX]> (LL) N) { 26 일 경우 (최대 <CNT * I) { 27 최대 = CNT * 난; 28 NUM = V; 29 (30) } 다른 경우 (CNT * I == 최대) NUM = 분 (NUM, V); 31 체류 ; 32 } 33 다른 DFS (INX + 1 , V * = PR [INX, CNT (* I + 1 ), I); 34 (35) } 36 } 37 38 // 反素数模板 39 무효 AntPrime () { 40 최대 = 1 ; 41 DFS ( 0 , 1 , 1 , 30 ); 42 } 43 44 공극 build_tree ( INT의 RT, INT L, INT R) { 45 트리 [RT] 펜닐 = L; 트리 [RT] .R = R; 46 의 경우 (L == R) { 47 의 경우 (L == S) = INX RT; (48) 트리 [RT] .value = 1 ; 49 창 ; 50 } 51 INT의 중간 = 트리 [RT] .MID (); 52 INT LSON = RT << 1 ; 53 INT rson = RT << 1 | 1 ; 54 build_tree (LSON, L, MID); 55 build_tree (rson 중간 + 1 , R); 56 트리 [RT] .value = 트리 [LSON] .value + 트리 [rson] .value; 57 } 58 59 공극 업데이트 ( INT X) { 60 반면(! X = . 1 ) { 61 인 - 트리 [X] .Value, 62는 X = >> 1이다. ] (63)이다 } 64 } 65 66 공극 검색 ( INT의 TOT, INT RT) { 67 // 위치 찾기 68 IF를 (트리 [ RT] .L == 트리 [RT] .R)는 { 69 SS는 = 트리 [RT] .L은; // 최초 큐 위치 70 INX = RT; // 세그먼트 트리의 위치가 업데이트 용이 71는 창 , 72 } (73) 인 INT LSON = RT <<. (1) , (74) INT RT = << rson . 1 | . 1 ; 75 IF (트리 [LSON] .Value> = TOT) 검색 (TOT, LSON) 76 다른 검색 (TOT - 트리 [LSON] .Value, rson) 77 } 78 79 공극 () {해결 80 그동안을 ((~는 scanf를 " % D % D " , 및 N-, ) S) { 81 build_tree를 ( 1. , 1. , N-)를, 82 AntPrime을 (); // GET emirp하고 약 수의 수 83 대 ( INT= I . 1 ; I <= N-; ++ I) { 84 는 scanf ( " % S % D " , P [I] .name과, P [I] 프로젝 터); 85 } 86 INT CNT = 0 ; 87 INT = REMAIN N-; 88 // S 자의 큐 위치에서 89 // SS는 사람의 최초 큐 위치 90 SS = S; 91은 그동안 (! ++ CNT = NUM) { 92 업데이트 (INX) // 세그먼트 트리를 갱신 (93) INT 돌려 = ABS (( 더블 ) P [SS] 프로젝 터); 94 턴 (%) = (남아 - 1 ); 95 의 경우 회전 = 남아 - (차례!) 1 ; 96 의 경우 (p [SS] 프로젝 터> 0 ) { 97 INT의 R의 남아 = - S; 98 의 경우 (R> = 턴) S = S + 턴 - 1 ; 99 다른 S = 턴 - R; 100 } 또 { 101 INT의 L 개의 S = - 1 ; 102 경우 (L> = 턴) S = 1 - 턴 + 1 ; (103 개) 다른 사람 들 = (남아 - 1) - (턴 - l) + 1 ; 104 } 105 // COUT은 << << SS << ENDL "위치는"; 106 // COUT << << P [SS] .name을 << ENDL "사람을 뛰어"; 107 됨 (S, 1 ); (108) - 남아; 109 } 110 의 printf ( " % S % D \ n " , P [SS] .name과, 최대); 111 } 112 } 113 114 INT 의 main () { 115 116 (해결); ; 119 }