import java.io.*; import java.util.*; /** * Estimation * @author vanb * * There are two parts to this algorithm. First, we've got to * compute costs[i][j], which is the error if we group together * A[i]..A[j]. Then, we've got to do some DP to find the best * partitioning. * * Fun Fact: For any group of numbers A[i]..A[j], the value C * which minimizes the error SUM{|A[k]-C|} for i<=k<=j is the median of A[i]..A[j]. * It's true - but it's left as an exercise for the reader to prove it. * * We'll compute the matrix of costs by using a binary tree to keep track * of the median. For efficiency, we'll use AVL balancing. Once we compute costs[i][j], * we'll do a DP to find the best partitioning. The DP will look like this: * * Let best[i][k] be the best you can do splitting A[0]..A[i] into k partitions. * Then best[i][k] = MIN{best[j][k-1] + costs[j+1][i]} for j1 ) { if( left.rightheight()>left.leftheight() ) { left.rotateleft(); } rotateright(); } else if( rightheight()-leftheight()>1 ) { if( right.leftheight()>right.rightheight() ) { right.rotateright(); } rotateleft(); } } } public Node root; /** * Do it! * @throws Exception */ public void doit() throws Exception { sc = new Scanner( System.in ); //new File( "estimate.in" ) ); ps = System.out; //new PrintStream( new FileOutputStream( "estimate.out" ) ); // Allocate everything beforehand int costs[][] = new int[2000][2000]; int best[][] = new int[2000][2000]; int a[] = new int[2000]; for(;;) { int n = sc.nextInt(); int p = sc.nextInt(); if( n==0 ) break; for( int i=0; ihi+1 ) { // Too many values are less than our current median. // We need to move it back by 1 value. int old = median.value; median = median.prev; --lo; ++hi; // This is the change in cost we incur by changing the median cost += (hi-lo)*(old-median.value); } else if( hi>lo+1 ) { // Too many values are greater than our current median. // We need to move it up by 1 value. int old = median.value; median = median.next; ++lo; --hi; // This is the change in cost we incur by changing the median cost += (lo-hi)*(median.value-old); } // This is the change in cost we incur by adding this new value. cost += Math.abs( median.value - node.value ); // Remember it! costs[i][j] = cost; } } // Now, the DP. // best[i][k] will be the best you can do // splitting a[0]..a[i] into k partitions. for( int i=0; i