사용법 #include <iostream> #INCLUDE <cstdio> #DEFINE LS (O) O << 1 #DEFINE RS (O) O << 1 | 1 사용 스페이스 성병; CONST INT의 WX = 50,017을; 인라인 INT 읽기 () { INT 합 = 0, F = 1; 숯 CH = getchar가 (); 동안 (CH2 <0 || CH> '9') {경우 (CH2 == '-') F = -1; CH = getchar가 ();} 동안 (CH2> = 0 && CH <=에서 '9') {합계 = SUM (<< 1) + (합 << 3) + CH-'0 '; CH = getchar가 ();} 환원 액 * F; }은 N INT, m; 구조체 SGT { INT의 L, R, 태그 lsum, rsum, 합; #DEFINE 태그 (O) t [0] .tag #DEFINE lsum (O) t [0] .lsum #DEFINE rsum (O) t [0] .rsum #DEFINE 합 (O) t [0] .sum } t [WX * 4; 경우 (SUM (LS (O)) == t [LS (O)]. RT [LS (O)]. L + 1) lsum (O) = SUM (LS (O)) + lsum (RS (O) ); 다른 lsum (O) = lsum (LS (O)); 경우 (SUM (RS (O)) == t [RS (O)]. RT [RS (O)]. L + 1) rsum (O) = SUM (RS (O)) + rsum (LS (O) ); 다른 rsum (O) = rsum (RS (O)); 합 (O) = 최대 (최대 (SUM (LS (O)), 합 (RS (O))) rsum (LS (O)) + lsum (RS (O))); } 보이드 다운 INT (O) { 경우 (태그 (O) == 0) { SUM (LS (O)) = lsum (LS (O)) = rsum (LS (O)) = t [LS (O)] . .rt [LS (O)] L + 1; .. 합 (RS (O)) = lsum (RS (O)) = rsum (RS (O))에서 t = [RS (O)]을 실온 [RS (O)] L + 1; 태그 (LS (O)) = 태그 (RS (O)) = 태그 (O); 태그 (O) = - 1; } 경우 (태그 (O) == 1) { SUM (LS (O)) = lsum (LS (O)) = rsum (LS (O)) = 0; 합계 (RS (O)) = lsum (RS (O)) = rsum (RS (O)) = 0; 태그 (LS (O)) = 태그 (RS (O)) = 태그 (O); 태그 (O) = - 1; } } 공극 빌드 (INT 오, INT의 L, R의 INT)을 { t [0] = L .L 단계; t [0] = R .R; 태그 (O) = - 1; 경우 (L == R)의 합 {(O) = lsum (O) = rsum (O) = 1; 반환} 미드의 t = [0] 펜닐 + t [0] int로 .R >> 1; (L <= MID) 빌드 (LS (O) L, MID)의 경우; 경우 (R> MID) 빌드 (RS (O), 미드 + 1, R); 최대 (O); } 공극 업데이트 (INT 오, INT의 L, INT의 R, INT의 k)를 { 경우 (L <= t [0] 펜닐 && t [0] .R <= R) { 경우 (! K) { 합 (O) = lsum (O) = rsum (O) = t의 [0] .rt [0] 펜닐 + 1; 태그 (O) = K; } 다른 { 합 (O) = lsum (O) = rsum (O) = 0; 태그 (O) = K; } 반환; } 아래 (O); INT의 중간 = t [0] + .L를 t [0] .R >> 1; 경우 (L <= MID) 업데이트 (LS (O), L, R, K); (R> MID) 업데이트 (RS (O)의 경우, L, R, 최대 (O); } INT 쿼리 (INT O, INT의 L, R의 INT, INT LEN) { 경우 (L == R) 복귀 L; 다운 (O); 경우. (t [LS (O)] 합계> = LEN) 리턴 질의 (LS (O), L, R, LEN); 다른 경우 (t [LS (O)] rsum + t [RS (O)] lsum> = LEN..) 반환 t [LS (O), R-rsum (LS (O)) + 1.; 그렇지 않은 경우 쿼리 (RS (O), L, R, 렌); } {) INT (주 ) (N = 판독; m = 판독 (); (1,1, N)를 작성; {위해 (; I <= m ++ 나 I = 1 INT) INT 선택 해제하는 단계; ) (= 판독 해제; 경우 (최적화 == 1) { INT (X); X = 판독 (); 경우 (SUM (1) <X) { 둔다 ( "0"); 계속하다; } INT의 쿼리 TMP = (1,1, N, X); 의 printf ( "% D \ 없음"TMP); 업데이트 (1, TMP, TMP + X-1,1); } 다른 { INT의 X, Y; X = 판독 (); Y는 판독 = (); 업데이트 (1, X, X + Y-1,0); } } 0을 리턴; }
인터넷에서 코드의 복사,하지만 불행히도, 즉, 나는이 세그먼트의 나무에 익숙하지 않았다가, 단지 세 개의 숫자가 실제로 오래 오래, 오른쪽 공간의 중간의 전체 길이 왼쪽 공간에서, 유지, 나는 충분히 생각 그래서 쓰기 분명이 바로 정상입니다