https://www.luogu.com.cn/problem/P4168
이름
$ $ A n의 숫자 및 보조 심문 $ m $, Q $ a_l, A_ {1 + 1} \ 도트 모드 A_R $ 무엇을
$ 1 \ leqslant n \ leqslant 40000, 1 \ leqslant m \ leqslant 50000, 1 \ leqslant A_I \ leqslant10 ^ 9 $
문제 해결
처음 블록
방법 1
통계 n이없는, 매우 크기 때문에 이후에 그렇게 할 수있는 개별 데이터의 수
그래서 당신은 직접 큰를 셀 수 있습니다. 이러한 복잡성은 확실히 $ \ mathcal {O} (m \ N 회) $, 타임 아웃 인
당신은 블록으로 분할 $ t의 $로, 사전에 어떤 블록 테이블을 재생하려고하고 최대 $ \하기 Binom {t} {2} 사전에 $ 블록을 배치하고, 이는 저장되어 있습니다
때마다 그래서 쿼리는 $ 2 \ 번 \ lfloor N / t \ rfloor $ 시간이, 시간 복잡도는 $ \입니다 mathcal {O} (t ^ 2N + 200 / t) $까지 지출
$ m $ 및 $ N- $ 동일한 순서로 간주 N에 상기 수득 $ t ^ 2N + 2N ^ 2 / t $, 동일한 정도의 크기를 보장하기 위해, 세트 $의 t는 2N = 2N ^ 2 / t $을 얻었다 ^ t = $ \ SQRT [3] {N} $
((A + B를) $을 증명 $ 최대 (a, b) = \ 세타 알고리즘 소개) 점차 크게 또는 복잡성 후보다 작은 양쪽이 증가하기 때문에, 전체 표현식의 복잡성 점진적 상승을 초래
AC 코드
#INCLUDE <cstdio> #INCLUDE <CString을> #INCLUDE <알고리즘> #INCLUDE <cmath> #INCLUDE <큐> #INCLUDE <벡터> 네임 스페이스를 사용하여 표준; 위한 #DEFINE REP (I, A, B) (등록 I = INT (a) I <(b); I ++) #DEFINE REPE (I, A, B)에 대한 (등록 I = INT (a) I < = (b); I ++) #DEFINE 페르 (I, A, B)에 대한 (등록 I = INT (a) I> = (B), 난 -) #ifdef와 sahdsg #DEFINE DBG (...)의 printf (__VA_ARGS__) #else #DEFINE DBG (...) 보이드 (0) #endif 다음 의 typedef 긴 긴 LL; #DEFINE MAXN 40,007 #DEFINE MAXM 50007 #DEFINE MAXD 35 INT A [MAXN], B [MAXN], C [MAXN]; INT D [MAXD] MAXD] MAXN]; 현재 값 int [MAXN]; INT t, L, NA; INT (X) = 0; 보이드는 인라인 (INT의 F) {한 지금 [F]를 ++; 경우 (현재 [NA] <지금 [F] || (현재 [NA] == 이제 [F] && 이제 [1 + NA]> F)) { 지금 [1 + NA = F; 이제 [NA가 이제 = [F] } } 인라인 INT (INT z의 INT Y) 이동 { INT I = (Z + L-1) / l, J = Y / l; INT L = I *은 L, R = J * L; 경우 (I <J) { REP (K, 0, NA + 2) 이제 [K] = D [I] [J] [K]; REP (F, Z, L) 않았다 (C [F]); REP (F, R, Y)의 한 (C [F]); } 다른 { memset 함수 (현재 0, sizeof 연산자 지금); REP (F, Z, Y)의 한 (C [F]); } 리턴 X = B [지금 [1 + NA]; } () {int로 메인 INT를 N, m; scanf와 ( "% D % D", 및 N, m); REP (I, 0, N)는 scanf {( "%의 D ', A [I]); B [I]은 [I]은} 정렬 (B, B + N); NA = 고유 (B, B + N) -b; REP (I, 0, n)이 { C [I] = LOWER_BOUND (B, B +, NA A [I]) - B; } memset 함수 (d, 0는 sizeof d); t = POW ((더블) N, (이중) 1/3); L = t? N / t : N; REP (I, 0, t) REPE (j, I, t) { REP (F, I는 L *, J * l) { INT의 K = C [F]; // DBG ( "* % D \ n" 케이); D [I] [J] [K] ++; 경우 (d [I] [J] [K]> D [I] [J] || (d [I] [J] [K] == D [NA] [I] [J] [NA] && K <D [I] [J] [1 + NA])) { D [I] [J] [NA = D [I] [J] [K]; D [I] [J] [1 + NA = K; } } } REP (I 0, m) { INT의 L0, R0; scanf와 ( "% D % D", L0, R0); L = INT (L0 + X - 1) + 1 %, N; INT R = (R0 + X - 1) + 1 %, N; (L> R) - 스왑 (L, R)의 경우; (L-1, R)으로 이동; 의 printf ( "가 % d \ n", X); }