Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

You are given $n$ packages of $w_i$ kg from a belt conveyor in order ($i = 0, 1, ... n-1$). You should load all packages onto $k$ trucks which have the common maximum load $P$. Each truck can load consecutive packages (more than or equals to zero) from the belt conveyor unless the total weights of the packages in the sequence does not exceed the maximum load $P$.

Write a program which reads $n$, $k$ and $w_i$, and reports the minimum value of the maximum load $P$ to load all packages from the belt conveyor.

Input

In the first line, two integers $n$ and $k$ are given separated by a space character. In the following $n$ lines, $w_i$ are given respectively.

Output

Print the minimum value of $P$ in a line.

Constraints

$1 \leq n \leq 100,000$

$1 \leq k \leq 100,000$

$1 \leq w_i \leq 10,000$

Sample Input 1

5 3
8
1
7
3
9

Sample Output 1

10

If the first truck loads two packages of $\{8, 1\}$, the second truck loads two packages of $\{7, 3\}$ and the third truck loads a package of $\{9\}$, then the minimum value of the maximum load $P$ shall be 10.

Sample Input 2

4 2
1
2
2
6

Sample Output 2

6

If the first truck loads three packages of $\{1, 2, 2\}$ and the second truck loads a package of $\{6\}$, then the minimum value of the maximum load $P$ shall be 6.

Solution in JAVA (judge verdict: Wrong Answer)

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;

public class Main {
	public static void main(String[] args) throws IOException {
		ContestScanner scan = new ContestScanner();

		final int n = scan.nextInt();
		final int k = scan.nextInt();
		final int[] wi = scan.nextIntArray(n);

		(new Solve(n, k, wi)).solve();
	}
}
class Solve {
	private final int n;
	private final int k;
	private final int[] wi;

	public Solve(final int n, final int k, final int[] wi)
	{
		this.n = n;
		this.k = k;
		this.wi = wi;
	}

	public void solve()
	{
		int sum = 0;
		int P = 0;
		int size = (n % k == 0) ? n / k : n / k + 1;

		int[] containers = new int[k];
		int[] containerSizeArray = new int[k];
		int[] containerPositions = new int[n];
		int[] sameCounts = new int[10001];
		OrderedIntList maxList = new OrderedIntList(100001);

		Arrays.fill(containers, 0);
		Arrays.fill(containerSizeArray, 0);
		Arrays.fill(sameCounts, 0);

		for(int i=0; i < n; i++) sum += wi[i];

		for(int i=0, j=0, count=0; i < n; i++)
		{
			containers[j] += wi[i];
			containerSizeArray[j]++;
			containerPositions[i] = j;
			maxList.insert(containers[j]);
			P = Math.max(P, containers[j]);

			count++;
			if(count == size)
			{
				count = 0;
				j++;
			}
		}

		for(int i=0; i < k; i++) sameCounts[containers[i]]++;

		maxList.removeLast();

		for(int i=0; i < n; i++)
		{
			P = Math.min(P, choice(wi, n, k, sum, P, containers, containerSizeArray, containerPositions, sameCounts, maxList, i));
		}
		System.out.println(P);
	}

	public int choice(final int[] wi, final int n, final int k, final int sum,
			int P, int[] containers, int[] containerSizeArray, int[] containerPositions, int[] sameCounts, OrderedIntList maxList, final int index)
	{
		if(index >= n) return P;

		final int pos = containerPositions[index];

		if( (index + 1 >= n || (containerPositions[index + 1] == containerPositions[index])) &&
			(index - 1 < 0 || (containerPositions[index - 1] == containerPositions[index])) )
		{
			return P;
		}


		final int w = wi[index];

		sameCounts[containers[pos]]--;

		containers[pos] -= w;
		containerSizeArray[pos]--;
		if(containers[pos] < P) maxList.insert(containers[pos]);

		sameCounts[containers[pos]]++;

		if(index + 1 < n && containerPositions[index + 1] > containerPositions[index])
		{
			if(sameCounts[P] == 0)
			{
				P = Math.min(P, Math.max(maxList.getLast(), containers[pos + 1] + w));
				if(P == maxList.getLast()) maxList.removeLast();
			}

			if(eval(n, containerSizeArray[pos + 1] + 1, containers[pos + 1] + w, sum) <= P)
			{
				sameCounts[containers[pos + 1]]--;
				containers[pos + 1] += w;
				containerSizeArray[pos + 1]++;
				containerPositions[index] = pos + 1;
				sameCounts[containers[pos + 1]]++;

				if(containers[pos + 1] < P) maxList.insert(containers[pos + 1]);

				for(int i = index+1; i < n; i++)
				{
					P = Math.min(P, choice(wi, n, k, sum, P, containers, containerSizeArray, containerPositions, sameCounts, maxList, index + 1));
				}

				if(containers[pos + 1] < P && sameCounts[containers[pos + 1]] == 1) maxList.remove(containers[pos + 1]);

				sameCounts[containers[pos + 1]]--;
				containerPositions[index] = pos;
				containerSizeArray[pos + 1]--;
				containers[pos + 1] -= w;
				sameCounts[containers[pos + 1]]++;
			}
		}

		if(index - 1 >= 0 && containerPositions[index - 1] < containerPositions[index])
		{
			if(sameCounts[P] == 0)
			{
				P = Math.min(P, Math.max(maxList.getLast(), containers[pos - 1] + w));
				if(P == maxList.getLast()) maxList.removeLast();
			}

			if(eval(n, containerSizeArray[pos - 1] + 1, containers[pos - 1] + w, sum) <= P)
			{
				sameCounts[containers[pos - 1]]--;
				containers[pos - 1] += w;
				containerSizeArray[pos - 1]++;
				containerPositions[index] = pos - 1;
				sameCounts[containers[pos - 1]]++;

				if(containers[pos - 1] < P) maxList.insert(containers[pos - 1]);

				for(int i = index+1; i < n; i++)
				{
					P = Math.min(P, choice(wi, n, k, sum, P, containers, containerSizeArray, containerPositions, sameCounts, maxList, index + 1));
				}

				if(containers[pos - 1] < P && sameCounts[containers[pos - 1]] == 1) maxList.remove(containers[pos - 1]);

				sameCounts[containers[pos - 1]]--;
				containerPositions[index] = pos;
				containerSizeArray[pos - 1]--;
				containers[pos - 1] -= w;
				sameCounts[containers[pos - 1]]++;
			}
		}

		sameCounts[containers[pos]]--;

		if(sameCounts[containers[pos]] == 0) maxList.remove(containers[pos]);

		containers[pos] += w;
		containerSizeArray[pos]++;

		sameCounts[containers[pos]]++;

		return P;
	}

	public int eval(final int n, final int currentContainerSize, final int weight, final int sum)
	{
		if(currentContainerSize == n) return sum;
		else return Math.max(weight, (sum - weight) / (n - currentContainerSize));
	}
}
class OrderedIntList {
	private int[] list;
	private int last;

	public OrderedIntList(final int size)
	{
		this.list = new int[size];
		this.last = -1;
	}

	public void insert(final int v)
	{
		if(this.last == -1)
		{
			this.last = 0;
			this.list[this.last] = v;
			return;
		}

		int min = 0;
		int max = this.last + 1;
		int mid = -1;

		while(min < max)
		{
			mid = (max + min) / 2;

			if(this.list[mid] == v) return;
			else if(this.list[mid] < v) min = mid + 1;
			else max = mid;
		}

		if(this.list[mid] < v)
		{
			for(int i=this.last; i > mid; i--)
			{
				this.list[i + 1] = this.list[i];
			}

			this.list[mid + 1] = v;
		}
		else
		{
			for(int i=this.last; i >= mid; i--)
			{
				this.list[i + 1] = this.list[i];
			}

			this.list[mid] = v;
		}
		this.last++;
	}


	public void remove(final int v)
	{
		if(this.last == -1)
		{
			return;
		}

		int min = 0;
		int max = this.last + 1;
		int mid = -1;

		while(min < max)
		{
			mid = (max + min) / 2;

			if(this.list[mid] == v) break;
			else if(this.list[mid] < v) min = mid + 1;
			else max = mid;
		}

		if(min == max) return;

		if(this.last > 0)
		{
			for(int i=mid; i < this.last; i++)
			{
				this.list[i] = this.list[i + 1];
			}
		}

		this.last--;
	}

	public int getLast()
	{
		return this.list[this.last];
	}

	public void removeLast()
	{
		this.last--;
	}

	public String toString()
	{
		String c = "";
		String result = "[";

		for(int i=0; i < this.last + 1; i++)
		{
			result += c + " " + this.list[i];
			c = ",";
		}
		return result + " ]";
	}
}
class ContestScanner {
	BufferedReader reader;
	String[] line;
	int index;
	public ContestScanner() {
		reader = new BufferedReader(new InputStreamReader(System.in));
	}

	public ContestScanner(String filename) throws FileNotFoundException {
		reader = new BufferedReader(new InputStreamReader(new FileInputStream(filename)));
	}

	public static interface ICreator<T> {
		public T createFromToken(final ContestScanner scanner) throws IOException;
	}

	public static interface IArrayInitializer {
		public void initialize(final ContestScanner scanner, final int i) throws IOException;
	}

	public static interface IObjectInitializer<T> {
		public T initialValue(final ContestScanner scanner);
	}

	public static class ObjectArrayInitializer<T> implements IArrayInitializer {
		protected T[] arr;
		protected final IObjectInitializer<T> initializer;

		private ObjectArrayInitializer(T[] arr, final IObjectInitializer<T> initializer)
		{
			this.arr = arr;
			this.initializer = initializer;
		}

		public static <T> ObjectArrayInitializer<T> create(T[] arr, final IObjectInitializer<T> initializer)
		{
			return new ObjectArrayInitializer<T>(arr, initializer);
		}

		public void initialize(final ContestScanner scanner, final int i) throws IOException {
			this.arr[i] = initializer.initialValue(scanner);
		}

		public T[] getArray()
		{
			return this.arr;
		}
	}


	public static class ByteArrayInitializer implements IArrayInitializer {
		protected byte[] arr;

		private ByteArrayInitializer(final int n)
		{
			this.arr = new byte[n];
		}

		public void initialize(final ContestScanner scanner, final int i) throws IOException {
			this.arr[i] = scanner.nextByte();
		}

		public byte[] getArray()
		{
			return this.arr;
		}
	}

	public static class ShortArrayInitializer implements IArrayInitializer {
		protected short[] arr;

		private ShortArrayInitializer(final int n)
		{
			this.arr = new short[n];
		}

		public void initialize(final ContestScanner scanner, final int i) throws IOException {
			this.arr[i] = scanner.nextShort();
		}

		public short[] getArray()
		{
			return this.arr;
		}
	}

	public static class IntArrayInitializer implements IArrayInitializer {
		protected int[] arr;

		private IntArrayInitializer(final int n)
		{
			this.arr = new int[n];
		}

		public void initialize(final ContestScanner scanner, final int i) throws IOException {
			this.arr[i] = scanner.nextInt();
		}

		public int[] getArray()
		{
			return this.arr;
		}
	}

	public static class LongArrayInitializer implements IArrayInitializer {
		protected long[] arr;

		private LongArrayInitializer(final int n)
		{
			this.arr = new long[n];
		}

		public void initialize(final ContestScanner scanner, final int i) throws IOException {
			this.arr[i] = scanner.nextLong();
		}

		public long[] getArray()
		{
			return this.arr;
		}
	}

	public static class FloatArrayInitializer implements IArrayInitializer {
		protected float[] arr;

		private FloatArrayInitializer(final int n)
		{
			this.arr = new float[n];
		}

		public void initialize(final ContestScanner scanner, final int i) throws IOException {
			this.arr[i] = scanner.nextFloat();
		}

		public float[] getArray()
		{
			return this.arr;
		}
	}

	public static class DoubleArrayInitializer implements IArrayInitializer {
		protected double[] arr;

		private DoubleArrayInitializer(final int n)
		{
			this.arr = new double[n];
		}

		public void initialize(final ContestScanner scanner, final int i) throws IOException {
			this.arr[i] = scanner.nextDouble();
		}

		public double[] getArray()
		{
			return this.arr;
		}
	}

	public String nextToken() throws IOException {
		if(line == null || index >= line.length)
		{
			line = reader.readLine().trim().split(" ");
			index = 0;
		}

		return line[index++];
	}

	public String next() throws IOException {
		return nextToken();
	}

	public String readLine() throws IOException {
		line = null;
		index = 0;

		return reader.readLine();
	}

	public byte nextByte() throws IOException, NumberFormatException {
		return Byte.parseByte(nextToken());
	}

	public short nextShort() throws IOException, NumberFormatException {
		return Short.parseShort(nextToken());
	}

	public int nextInt() throws IOException, NumberFormatException {
		return Integer.parseInt(nextToken());
	}

	public long nextLong() throws IOException, NumberFormatException {
		return Long.parseLong(nextToken());
	}

	public float nextFloat() throws IOException, NumberFormatException {
		return Float.parseFloat(nextToken());
	}

	public double nextDouble() throws IOException, NumberFormatException {
		return Double.parseDouble(nextToken());
	}

	public <T> T nextObject(final ICreator<T> creator) throws IOException, NumberFormatException {
		return creator.createFromToken(this);
	}

	public int[] nextIntArray(final int N) throws IOException, NumberFormatException {
		int[] result = new int[N];

		for(int i=0; i < N; i++) result[i] = nextInt();

		return result;
	}

	public long[] nextLongArray(final int N) throws IOException, NumberFormatException {
		long[] result = new long[N];

		for(int i=0; i < N; i++) result[i] = nextLong();

		return result;
	}

	public float[] nexFloatArray(final int N) throws IOException, NumberFormatException {
		float[] result = new float[N];

		for(int i=0; i < N; i++) result[i] = nextFloat();

		return result;
	}

	public double[] nexDoubleArray(final int N) throws IOException, NumberFormatException {
		double[] result = new double[N];

		for(int i=0; i < N; i++) result[i] = nextDouble();

		return result;
	}

	public <T> T[] nextObjectArray(T[] result, final ICreator<T> creator) throws IOException, NumberFormatException {
		for(int i=0, N=result.length; i < N; i++) result[i] = nextObject(creator);

		return result;
	}

	public <T> ArrayList<T> nextGenericObjectArrayList(final int N, final ICreator<T> creator) throws IOException, NumberFormatException {
		ArrayList<T> result = new ArrayList<T>();
		for(int i=0; i < N; i++) result.add(nextObject(creator));

		return result;
	}

	public void nextTable(final int N, IArrayInitializer... arrayInitializers) throws IOException, NumberFormatException {
		for(int i=0; i < N; i++) for(IArrayInitializer initializer: arrayInitializers)
		{
			initializer.initialize(this, i);
		}
	}
}