Minimum Sum

**Time Limit: 16000/8000 MS (Java/others) memory limit: 65536/32768 K (Java/Others)**

Total submission (s): 1533 accepted submission (s): 345

Problem descriptionyou are given n positive integers, denoted as x0, X1... xN-1. then give you some intervals [L, R]. for each interval, you need to find a number X to make as small as possible!

Inputthe first line is an integer T (t <= 10), indicating the number of test cases. for each test case, an integer N (1 <= n <= 100,000) comes first. then comes n positive integers x (1 <= x <= 1,000,000,000) in the next line. finally, comes an integer Q (1 <= q <= 100,000), indicting there are Q queries. each query consists of two integers L, R (0 <= L <= r <n), meaning the interval you shoshould deal.

Outputfor the k-th test case, first output "Case # K:" in a separate line. then output Q lines, each line is the minimum value. output a blank line after every test case.

Sample input2 5 3 6 2 2 2 1 4 0 2 7 7 2 0 1 1 1

Sample outputcase #1: 6 4 case #2: 0 0

Authorstandy

Source2010ACM-ICPC multi-university training Contest (4) -- host by UESTC

Recommendzhengfeng is the partition tree. It is easy to know that when X is the median, the formula in the question is the smallest. Add sum [I] [J] to record the sum of numbers in layer I 1-j. Then, calculate the sum of values greater than the median and the sum of values smaller than the median. Code .

/* HDU 3473 minimum sumac g ++ 546 Ms 29000 K */ # Include <Stdio. h> # Include < String . H> # Include <Iostream> # Include <Algorithm>Using Namespace STD; Const Int Maxn = 200010 ; Int Tree [ 20 ] [Maxn]; Int Sorted [maxn]; Int Toleft [ 20 ] [Maxn]; Long Long Sum [ 20 ] [Maxn]; Void Build ( Int L, Int R, Int Dep ){ If (L = R) {sum [Dep] [l] = Tree [Dep] [l]; Return ;} Int Mid = (L + r)>1 ; Int Same = mid-L + 1 ; // Same indicates the number of numbers equal to the center value and to the left. For ( Int I = L; I <= r; I ++ ){ If (Tree [Dep] [I] < Sorted [Mid]) Same -- ; Sum [Dep] [I] = Tree [Dep] [I]; If (I> L) sum [Dep] [I] + = sum [Dep] [I- 1 ];} Int LPOS = L; Int Rpos = Mid + 1 ; For ( Int I = L; I <= r; I ++ ){ If (Tree [Dep] [I] <sorted [Mid]) // Go to left {Tree [Dep +1 ] [LPOS ++] = Tree [Dep] [I];} Else If (Tree [Dep] [I] = sorted [Mid] & same> 0 ) // Go to left {Tree [Dep + 1 ] [LPOS ++] = Tree [Dep] [I]; same -- ;} Else // Go to the right Tree [Dep + 1 ] [Rpos ++] = Tree [Dep] [I]; toleft [Dep] [I] = Toleft [Dep] [l- 1 ] + LPOS-L; // Number of places from 1 to I on the left } Build (L, mid, Dep + 1 ); // Recursive build Build (Mid + 1 , R, DEP + 1 );} Long Long Ans; Int Query ( Int L, Int R, Int L, Int R, Int Dep, Int K ){ If (L = r) Return Tree [Dep] [l]; Int Mid = (L + r)>1 ; Int CNT = toleft [Dep] [r]-toleft [Dep] [l- 1 ]; Int Ss = toleft [Dep] [l- 1 ]-Toleft [Dep] [l- 1 ]; Int EE = L-l- SS; Int S = toleft [Dep] [r]-toleft [Dep] [l- 1 ]; Int E = r-L + 1 - S; If (CNT> = K ){ If (E> 0 ){ If (EE> 0 ) Ans + = sum [Dep + 1 ] [Mid + E + EE]-sum [Dep + 1 ] [Mid + EE]; Else Ans + = sum [Dep +1 ] [Mid + E];} // L + number of numbers to the left before the query Interval Int Newl = L + toleft [Dep] [l- 1 ]-Toleft [Dep] [l- 1 ]; // The left endpoint + query interval will be split into the number on the left Int Newr = newl + CNT- 1 ; Return Query (L, mid, newl, newr, DEP +1 , K ); // Note: } Else { If (S> 0 ){ If (Ss> 0 ) Ans-= sum [Dep + 1 ] [L + SS + S- 1 ]-Sum [Dep + 1 ] [L + SS- 1 ]; Else Ans-= sum [Dep + 1 ] [L + S- 1 ];} // Number of left-side splits after the R + interval Int Newr = R + toleft [Dep] [r]- Toleft [Dep] [r]; // Number of right endpoint minus the number of right-side partitions Int Newl = newr-(R-l- CNT ); Return Query (Mid +1 , R, newl, newr, DEP + 1 , K-CNT ); // Note: }} Int Main (){ // Freopen ("in.txt", "r", stdin ); // Freopen ("out.txt", "W", stdout ); Int T; Int N, m; scanf ( " % D " ,& T ); Int L, R; Int Icase = 0 ; While (T -- ) {Icase ++ ; Scanf ( " % D " ,& N ); For ( Int I = 1 ; I <= N; I ++ ) {Scanf ( " % D " , & Tree [ 0 ] [I]); sorted [I] = Tree [ 0 ] [I];} Sort (sorted + 1 , Sorted + 1 + N); Build ( 1 , N, 0 ); Printf ( " Case # % d: \ n " , Icase); scanf ( " % D " ,& M ); While (M -- ) {Scanf ( " % D " , & L ,& R); L ++ ; R ++ ; Ans = 0 ; Int Tt = query ( 1 , N, l, R, 0 , (R-l )/ 2 + 1 ); If (R-l + 1 ) % 2 = 0 ) {Ans -= TT;} printf ( " % I64d \ n " , ANS);} printf ( " \ N " );} Return 0 ;}