Hi everyone,
This is one of the problems used in our National Olympiad in Informatics, and it has remained unsolved since 2005. Your help would be really appreciated! So here it is:
Given a sequence of N elements a[1], a[2], ..., a[N] and a positive number K. A partition is defined to include several consecutive elements in the original sequence. Write a program that splits the given sequence into k partitions such that the maximum sum among those partitions is minimized. Write out the desired sum.
Constraints:
1 ≤ k ≤ n ≤ 15000
|ai| ≤ 30000
Example:
Input
9 4 (N and K)
1 1 1 3 2 2 1 3 1 (a[1], a[2], ..., a[N]
Output
5
Explain:
We can divide the original sequence into 4 partitions:
(1, 1, 1)
(3, 2)
(2, 1)
(3, 1)
The maximum sum among the partitions above is 5 (= 3 + 2), and it is the best minimum sum we can achieve while splitting the sequence into 4 partitions.
Binary search?
Could you please tell me more in details?
You could google what means "binary search". Then you could apply it for searching answer. You need only check if it is possible to split sequence in k subsequences with sum less than x. You could do it greedy
you told the easy part ,but for each binary search iteration how to check if there's an answer?
How this greedy works?
greedy adding from left to right until sum less x or negative segment. You could precalc right ends of negative segments walking from right to left.
How to ensure that we used exactly K partitions?
for example let this array that we should check if we can divide it into 2 parts with sum less than 3
5 -3
we can make the first part less than 3 by taking both 5 and -3 but in this case will not remain any numbers for the second partition
In statement was no information about subsequences should be nonempty.
this problem exists on spoj
Could you please tell me about the idea of solving the problem?
I also don't know how to solve it
Well, I found out this solution yesterday, but I don't quite understand how he used a Binary Search Tree (seems like a Treap) to handle the DP relation (step 3). Is there anybody get it?
i dont understand greedy solution proof at all but dp solution + binary search makes sense. first use binary search for M (maximum sum) than with dp check is there a solution .
in dp
F[i] = for segment [i,N] , maxsimum K
then we can calculate all F from right to left , in each stepF[i] = i<j && sum(i,j)<=M max(F[j]+1)
andG[i] = for segment [i,N] , minimum K
in each stepG[i] = i<j && sum(i,j)<=M min(G[j]+1)
ifF[1]>=K
andG[1]<=K
we can assume that there is a solution. for calculate F and G efficient use segment tree . overall complexityO(N.log N.log N)
Can you be more specific about how to use segment tree to calculate F and G?
use segment such that
segment[i] = k
. it means that there isj range_sum[1,j] = i
andf(i) = k
. so for calculate F in i.th position while iterating from right to left you can get solution from segment tree withquery(sum[i]-m,inf)
I'm sorry, but I'm still a little foggy about your approach. In the range_sum[1, j] = i, shouldn't i be very large? Or maybe I'm misunderstanding the way you do. Is range_sum[1, j] = a[1] + a[2] + ... + a[j]? And what is k here? Is it the k given in the input?
Thank you!
first k = how many partition , range_sum[i,j] = a[i] + a[i+1] + .. ar[j]
second yes you are right you have to give all these number id so you compress them like that
-5 10 1548944 10 123 434442
then compress
1 2 5 2 3 4
~~~~~after this operation maximum element is at most N . here is implementation with segment and with fenwick . fenwick is 5 times faster than classic segment .
How can you prove this statement ? " if F[1]>=K and G[1]<=K we can assume that there is a solution."
if all numbers were in positive just finding minimum number of partitions is enough . proof is simple we have k partitions each of them is less then M so for more partitions we can just divide them into 2 partitions so that k increase by one . if we have also negative numbers we have to calculate maxsimum k also .
You didn't convince me, what's the formal and general proof for the assumption you just made ? I'd like to see a formal proof.
OK, I got accepted with a mix of the ideas thrown in this thread. I'll explain my solution...
If you want to check the code, see here -> C++ solution