Problem:
Problem H:
Round Table
You are the owner of a restaurant, and you are serving for
N
customers seating in a round table.
You will distribute
M
menus to them. Each customer receiving a menu will make the order of plates, and
then pass the menu to the customer on the right unless he or she has not make the order. The customer
i
takes
L
i
unit time for the ordering.
Your job is to write a program to calculate the minimum time until all customers to call their orders, so you can improve your business performance.
Input
The input consists of a sequence of positive integers.
The first line of the input contains two positive integers
N
(
N
≤ 50,000) and
M
(
M
≤
N
). The second line contains
N
positive integers
L
1
,
L
2
,...,
L
N
(
L
i
≤ 600).
Output
Output the minimum possible time required for them to finish ordering.
Sample Input and Output
Input #1
3 2
1 5 10
Output #1
10
Input #2
4 2
1 2 3 4
Output #2
5

Submitted solutions:

code_snippet: #include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<list>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#include<string>
#define sgn(v) (abs((v))<eps?0:((v)<0?-1:1))
#define sqr(v) ((v)*(v))
#define MP make_pair
#define PB push_back
#define FI first
#define SE second
#define debug 0
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<double,int> PDI;
typedef pair<double,double> PDD;
typedef pair<int,int> PII;
typedef pair<int,LL> PIL;
typedef pair<LL,int> PLI;
typedef pair<LL,LL> PLL;
const double eps=1e-8;
const double pi=acos(-1);
const int maxn=5e4+100;
int sum[maxn*3],L[maxn*3],nxt[maxn*3][21];
int n,m,maxv;
bool check(int v)
{
	//cout <<"when:"<<v<<" "<<maxv<<endl;
	if(v<maxv)return false;
	int i,j,l,r,con;
	for(i=1;i<=3*n+1;++i)
		for(j=0;j<=20;++j)nxt[i][j]=3*n+1;
	for(i=1;i<=3*n;++i)
	{
		l=i,r=3*n;
		while(l<r)
		{
			int mid=l+r+1>>1;
			if(sum[mid]-sum[i-1]<=v)l=mid;
			else r=mid-1;
		}
		nxt[i][0]=l+1;
	}
	//cout <<"when:"<<v<<endl;for(i=1;i<=3*n;++i)cout <<nxt[i][0]<<" ";cout <<endl;
	for(i=3*n;i>=1;--i)
		for(j=1;j<=20;++j)
			nxt[i][j]=nxt[nxt[i][j-1]][j-1];
	for(i=1;i<=n;++i)
	{
		l=i;
		con=0;
		for(j=20;j>=0&&l!=3*n+1;--j)
		{
			if(m>=con+(1<<j))
			{
				l=nxt[l][j];	
				con+=(1<<j);
				//cout <<i<<" "<<l<<" "<<(1<<j)<<endl;
			}
		}
		if(l-i>=n)return true;
	}
	return false;
}
int main()
{
	int i;
	scanf("%d%d",&n,&m);
	maxv=0;
	for(i=1;i<=n;++i)
	{
		scanf("%d",&L[i]);
		maxv=max(maxv,L[i]);
	}
	for(i=1;i<=n;++i)
		sum[i]=sum[i-1]+L[i];
	for(i=n+1;i<=2*n;++i)
		sum[i]=sum[i-1]+L[i-n];
	for(i=2*n+1;i<=3*n;++i)
		sum[i]=sum[i-1]+L[i-2*n];
	int l=0,r=sum[n];
	while(l<r)
	{
		int mid=l+r>>1;
		//cout <<l<<" "<<r<<" "<<mid<<endl;
		if(check(mid))r=mid;
		else l=mid+1;
	}
	printf("%d\n",l);
	return 0;
}
accuracy: 1
time_ms: 280
memory_kb: 16656
final_rank: 11

code_snippet: #include <bits/stdc++.h>

using namespace std;

int n, m;
int a[100001];

bool check(int x) {
    int j = 0;
    int sum = 0;
    int nxt[n * 2 + 1];
    int L = 0, R = n * 2;
    for (int i = 1; i <= n * 2; i++) {
        while (j <= n * 2 && sum + a[j + 1] <= x) {
            sum += a[j + 1];
            j++;
        }
        nxt[i] = j + 1;
        if (i <= n && nxt[i] - i < R - L) {
            L = i, R = nxt[i];
        }
        sum -= a[i];
    }
    for (int i = L; i <= R; i++) {
        int cnt = 0;
        int l = i;
        if (l > n)
            l -= n;
        for (j = l; j < l + n; j = nxt[j]) {
            cnt++;
        }
        if (cnt <= m)
            return 1;
    }
    return 0;
}

int main() {
    cin >> n >> m;
    int mx = 0;
    int sum = 0;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        sum += a[i];
        mx = max(mx, a[i]);
        a[i + n] = a[i];
    }
    int l = mx, r = sum;
    while (l <= r) {
        int mid = (l + r) / 2;
        if (check(mid))
            r = mid - 1;
        else l = mid + 1;
    }
    cout << l << "\n";
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4216
final_rank: 7

code_snippet: #include <bits/stdc++.h>
#define INF 1000000007
#define MP make_pair
#define FI first
#define SE second
#define PB push_back
#define VI vector<int>
const double EPS = 1e-7, PI = acos(-1.0);
using namespace std;
typedef long long LL;
typedef pair <int, int> P;
const int NUM = 100010;
int n, m, L[NUM];
int first[NUM], len[NUM];
int solve(int t)
{
    int res = n, sum = 0, i, j;
    memset(len, -1, sizeof(len));
    for(i = 0; i < n && sum + L[i] <= t; ++i) first[i] = i + 1, sum += L[i], len[i] = 0;
    if(i == n) return 1;
    len[i - 1] = 1;
    first[i - 1] = 0;
    for(j = 0; j < n; ++j)
	{
		sum -= L[j];
		for(;i < n + n && sum + L[i] <= t; ++i)
		{
			sum += L[i];
			len[i] = len[j] + 1;
			first[i] = first[j];
//			cout<<i << ' ' << j <<' ' << len[i] << ' ' << first[i] << endl;
			if(i - first[i] + 1 >= n) res = min(res, len[i]);
		}
	}
    return res;
}
int main()
{
#ifdef ACM_TEST
    freopen("in.txt", "r", stdin);
#endif
    scanf("%d%d", &n, &m);
    int l = 0, r = 0, mid, ans = 0;
    for(int i = 0; i < n; ++i)
    {
        scanf("%d", &L[i]);
        L[i + n] = L[i];
        l = max(l, L[i]);
        r += L[i];
    }
//    l = r = 15;
    while(l <= r)
    {
        mid = (l + r) >> 1;
        if(solve(mid) <= m)
        {
            r = mid - 1;
            ans = mid;
        }
        else
        {
            l = mid + 1;
        }
    }
    printf("%d\n", ans);
    return 0;
}
accuracy: 0.96875
time_ms: 10
memory_kb: 4636
final_rank: 17

code_snippet: // AOJ #2475 Round Table
// 2025.4.16

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {
	int n = 0; int c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

int N, M;
vector<int> L;
vector<int> A;
vector<ll> P;
int len;
vector<int> nxt;
vector<vector<int>> dp;
int LOG;

bool possible(ll T) {
    len = 2 * N;
    A.resize(len);
    for (int i = 0; i < len; i++) A[i] = L[i % N];
    P.resize(len + 1);
    P[0] = 0;
    for (int i = 0; i < len; i++) P[i+1] = P[i] + A[i];

    nxt.assign(len, 0);
    int j = 0;
    for (int i = 0; i < len; i++) {
        if (j < i) j = i;
        while(j < len && P[j+1] - P[i] <= T) j++;
        nxt[i] = j;
    }

    LOG = 1;
    while ((1 << LOG) <= N) LOG++;
    dp.assign(LOG, vector<int>(len, 0));
    for (int i = 0; i < len; i++) dp[0][i] = nxt[i];
    for (int k = 1; k < LOG; k++){
        for (int i = 0; i < len; i++){
            int mid = dp[k-1][i];
            dp[k][i] = (mid < len ? dp[k-1][mid] : mid);
        }
    }

    int best = N + 1;
    for (int i = 0; i < N; i++){
        int cnt = 0;
        int cur = i;
        int target = i + N;
        for (int k = LOG - 1; k >= 0; k--){
            if(cur < target && dp[k][cur] < target) {
                cnt += (1 << k);
                cur = dp[k][cur];
            }
        }
        if(cur < target) cnt++;
        best = min(best, cnt);
    }
    return best <= M;
}

int main(){
    N = Cin(), M = Cin();
    L.resize(N);
    int maxL = 0;
    ll sum = 0;
    for (int i = 0; i < N; i++){
        L[i] = Cin();
        maxL = max(maxL, L[i]);
        sum += L[i];
    }

    ll lo = maxL, hi = sum, ans = hi;
    while(lo <= hi) {
        ll mid = (lo + hi) / 2;
        if (possible(mid)) ans = mid, hi = mid - 1;
        else lo = mid + 1;
    }
    printf("%lld\n", ans);
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 11500
final_rank: 10

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 50005

int N,M;
ll table[2*NUM];


bool is_ok(ll value,int start_index){

	ll num_section,base,next_base;
	int L,R,mid;

	for(int start = start_index; start <= start_index; start++){

		num_section = 0;
		base = start;

		while(base < N+start){

			//2分探索で、総和がvalue以下となる最大のインデックスを求める
			L = 0,R = start+N-1-base,mid = (L+R)/2;

			while(L <= R){

				if(table[base+mid]-table[base-1] <= value){

					next_base = base+mid+1;
					L = mid+1; //より区間を長く

				}else{

					R = mid-1;
				}
				mid = (L+R)/2;
			}

			num_section++;

			base = next_base;

			//残りを最大化しても、総和が足りなければ不可
			if(value*(M-num_section) < table[start+N-1]-table[base-1]){
				return false;
			}
		}

		if(num_section <= M){
			return true;
		}
	}

	return false; //区間分割数がM以下か
}



int main(){

	scanf("%d %d",&N,&M);

	ll maximum = 0;

	table[0] = 0;
	for(int i = 1; i <= N; i++){

		scanf("%lld",&table[i]);
		table[i+N] = table[i];
		maximum = max(maximum,table[i]);
	}

	for(int i = 1; i <= 2*N; i++){

		table[i] += table[i-1];
	}

	ll L = maximum, R = table[N], mid = (L+R)/2;
	ll ans = BIG_NUM;

	while(L <= R){

		if(is_ok(mid,1)){

			ans = mid;
			R = mid-1;
		}else{

			L = mid+1;
		}

		mid = (L+R)/2;

	}

	L = maximum,R = ans,mid = (L+R)/2;
	int left,right,m,start_index,end_index;

	vector<int> V;

	while(L <= R){

		//2から数えて、合計がmidを超えない最大の右端を求める
		left = 2,right = N+1,m = (left+right)/2;
		end_index = 2;

		while(left <= right){

			if(table[m]-table[1] <= mid){

				end_index = m;
				left = m+1; //より右へ

			}else{

				right = m-1;
			}
			m = (left+right)/2;
		}

		V.clear();
		for(int i = 2; i <= end_index; i++){
			V.push_back(i);
		}

		//左端を求める
		ll tmp_sum = table[end_index]-table[1];

		if(end_index == N+1){

			//Do nothing
		}else{

			left = end_index+1,right = N+1,m = (left+right)/2;
			start_index = N+1;

			while(left <= right){

				if(table[N+1]-table[m-1]+tmp_sum <= mid){

					start_index = m;
					right = m-1; //より左へ

				}else{

					left = m+1;
				}
				m = (left+right)/2;
			}

			for(int i = start_index; i <= N+1; i++){

				V.push_back(i);
			}
		}

		bool FLG = false;

		for(int i = 0; i < V.size(); i++){

			if(is_ok(mid,V[i])){
				FLG = true;
				break;
			}
		}

		if(FLG){ //少なくとも一件成功すれば良し

			ans = mid;
			R = mid-1;

		}else{

			L = mid+1;
		}

		mid = (L+R)/2;
	}

	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 4140
final_rank: 6

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 50005

int N,M;
ll table[2*NUM];


bool is_ok(int value,int start_index){

	int num_section,base,next_base;
	int L,R,mid;

	for(int start = start_index; start <= start_index; start++){

		num_section = 0;
		base = start;

		while(base < N+start){

			//2分探索で、総和がvalue以下となる最大のインデックスを求める
			L = 0,R = start+N-1-base,mid = (L+R)/2;

			while(L <= R){

				if(table[base+mid]-table[base-1] <= value){

					next_base = base+mid+1;
					L = mid+1; //より区間を長く

				}else{

					R = mid-1;
				}
				mid = (L+R)/2;
			}

			num_section++;

			base = next_base;
		}

		if(num_section <= M){
			return true;
		}
	}

	return false; //区間分割数がM以下か
}



int main(){

	scanf("%d %d",&N,&M);

	ll maximum = 0;

	table[0] = 0;
	for(int i = 1; i <= N; i++){

		scanf("%lld",&table[i]);
		table[i+N] = table[i];
		maximum = max(maximum,table[i]);
	}

	for(int i = 1; i <= 2*N; i++){

		table[i] += table[i-1];
	}

	ll L = maximum, R = table[N], mid = (L+R)/2;
	ll ans = BIG_NUM;

	while(L <= R){

		if(is_ok(mid,1)){

			ans = mid;
			R = mid-1;
		}else{

			L = mid+1;
		}

		mid = (L+R)/2;

	}

	L = maximum,R = ans,mid = (L+R)/2;
	int left,right,m,start_index,end_index;

	vector<int> V;

	while(L <= R){

		//2から数えて、合計がmidを超えない最大の右端を求める
		left = 2,right = N+1,m = (left+right)/2;
		end_index = 2;

		while(left <= right){

			if(table[m]-table[1] <= mid){

				end_index = m;
				left = m+1; //より右へ

			}else{

				right = m-1;
			}
			m = (left+right)/2;
		}

		V.clear();
		for(int i = 2; i <= end_index; i++){
			V.push_back(i);
		}

		//左端を求める
		ll tmp_sum = table[end_index]-table[1];

		if(end_index == N+1){

			//Do nothing
		}else{

			left = end_index+1,right = N+1,m = (left+right)/2;
			start_index = N+1;

			while(left <= right){

				if(table[N+1]-table[m-1]+tmp_sum <= mid){

					start_index = m;
					right = m-1; //より左へ

				}else{

					left = m+1;
				}
				m = (left+right)/2;
			}

			for(int i = start_index; i <= N+1; i++){

				V.push_back(i);
			}
		}

		bool FLG = false;

		for(int i = 0; i < V.size(); i++){

			if(is_ok(mid,V[i])){
				FLG = true;
				break;
			}
		}

		if(FLG){ //少なくとも一件成功すれば良し

			ans = mid;
			R = mid-1;

		}else{

			L = mid+1;
		}

		mid = (L+R)/2;
	}

	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 4052
final_rank: 5

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 50005

int N,M;
ll table[2*NUM];


bool is_ok(int value){

	int num_section,base,next_base;
	int L,R,mid;

	for(int start = 1; start <= 1; start++){

		num_section = 0;
		base = start;

		while(base < N+start){

			//2分探索で、総和がvalue以下となる最大のインデックスを求める
			L = 0,R = start+N-1-base,mid = (L+R)/2;

			while(L <= R){

				if(table[base+mid]-table[base-1] <= value){

					next_base = base+mid+1;
					L = mid+1; //より区間を長く

				}else{

					R = mid-1;
				}
				mid = (L+R)/2;
			}

			num_section++;

			base = next_base;
		}

		if(num_section <= M){
			return true;
		}
	}

	return false; //区間分割数がM以下か
}


bool is_ok2(ll value,int end){

	if(value*M < table[N])return false;

	ll num_section,base,next_base;
	ll L,R,mid;

	for(int start = 2; start <= end; start++){

		num_section = 0;
		base = start;

		while(base < N+start){

			//2分探索で、総和がvalue以下となる最大のインデックスを求める
			L = 0,R = start+N-1-base,mid = (L+R)/2;

			while(L <= R){

				if(table[base+mid]-table[base-1] <= value){

					next_base = base+mid+1;
					L = mid+1; //より区間を長く

				}else{

					R = mid-1;
				}
				mid = (L+R)/2;
			}

			num_section++;

			base = next_base;

			//残りを最大化しても、総和が足りなければ不可
			if(value*(M-num_section) < table[start+N-1]-table[base-1]){
				//printf("Dog\n");
				num_section = M+1;
				break;
			}
		}

		if(num_section <= M){
			return true;
		}
	}

	return false; //区間分割数がM以下か
}


int main(){

	scanf("%d %d",&N,&M);

	ll maximum = 0;

	table[0] = 0;
	for(int i = 1; i <= N; i++){

		scanf("%lld",&table[i]);
		table[i+N] = table[i];
		maximum = max(maximum,table[i]);
	}

	for(int i = 1; i <= 2*N; i++){

		table[i] += table[i-1];
	}

	ll L = maximum, R = table[N], mid = (L+R)/2;
	ll ans = BIG_NUM;

	/*printf("L:%d R:%d\n",L,R);
	return 0;*/

	while(L <= R){

		if(is_ok(mid)){

			ans = mid;
			R = mid-1;
		}else{

			L = mid+1;
		}

		mid = (L+R)/2;

	}

	//printf("maximum:%d ans:%d\n",maximum,ans);

	L = maximum,R = ans,mid = (L+R)/2;
	int left,right,m,end;

	while(L <= R){

		//2から数えて、合計がmidを超えない最大の右端を求める
		left = 2,right = N+1,m = (left+right)/2;
		end = 2;

		while(left <= right){

			if(table[m]-table[1] <= mid){

				end = m;
				left = m+1; //より右へ

			}else{

				right = m-1;
			}
			m = (left+right)/2;
		}

		if(is_ok2(mid,end)){

			ans = mid;
			R = mid-1;
		}else{
			//printf("不可\n");
			L = mid+1;
		}

		mid = (L+R)/2;
	}

	printf("%lld\n",ans);

	return 0;
}
accuracy: 0.96875
time_ms: 20
memory_kb: 3960
final_rank: 16

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
  int n,m;
  cin>>n>>m;
  int a[n*2],sum=0,ma=0;
  for(int i=0;i<n;i++){
    cin>>a[i];
    a[n+i]=a[i];
    sum+=a[i];
    ma=max(ma,a[i]);
  }
  srand((unsigned)time(NULL));
  time_t start=clock();
  set<int> s;
  int ans=sum;
  while((double)(clock()-start)/CLOCKS_PER_SEC<7.0){
    int p=rand()%n;
    if(s.count(p)) continue;
    s.insert(p);
    int l=ma-1,r=sum;
    while(l+1<r){
      int mid=(l+r)/2;
      int v=p,t=a[p],c=0;
      while(1){
    while(v+1<p+n&&t+a[v+1]<=mid){
      v++;
      t+=a[v];
    } 
    c++;t=0;
    if(v+1>=p+n) break;
      }
      if(c<=m) r=mid;
      else l=mid;
    }
    //cout<<r<<endl;
    ans=min(ans,r);
  }
  cout<<ans<<endl;
  return 0;
}
accuracy: 1
time_ms: 7000
memory_kb: 4152
final_rank: 13

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
  int n,m;
  cin>>n>>m;
  int a[n*2],sum=0,ma=0;
  for(int i=0;i<n;i++){
    cin>>a[i];
    a[n+i]=a[i];
    sum+=a[i];
    ma=max(ma,a[i]);
  }
  srand((unsigned)time(NULL));
  time_t start=clock();
  set<int> s;
  int ans=sum;
  while((double)(clock()-start)/CLOCKS_PER_SEC<7.0){
    int p=rand()%n;
    if(s.count(p)) continue;
    s.insert(p);
    int l=ma-1,r=sum;
    while(l+1<r){
      int mid=(l+r)/2;
      int v=p,t=a[p],c=0;
      while(1){
	while(v+1<p+n&&t+a[v+1]<=mid){
	  v++;
	  t+=a[v];
	} 
	c++;t=0;
	if(v+1>=p+n) break;
      }
      if(c<=m) r=mid;
      else l=mid;
    }
    //cout<<r<<endl;
    ans=min(ans,r);
  }
  cout<<ans<<endl;
  return 0;
}
accuracy: 1
time_ms: 7000
memory_kb: 4116
final_rank: 12

code_snippet: #include <bits/stdc++.h>
#define INF 1000000007
#define MP make_pair
#define FI first
#define SE second
#define PB push_back
#define VI vector<int>
const double EPS = 1e-7, PI = acos(-1.0);
using namespace std;
typedef long long LL;
typedef pair <int, int> P;
const int NUM = 100010;
int n, m, L[NUM];
int nxt[NUM], vis[NUM];
int solve(int t)
{
    int sum = 0;
    for(int i = 0, j = 0; i < n + n; ++i)
    {
        while(j < n + n && sum + L[j] <= t) sum += L[j++];
        nxt[i] = j;
        sum -= L[i];
    }
    int res = -1;
    for(int i = 0; i < nxt[0]; ++i)
    {
        sum = 0;
        for(int j = i; j - i < n; j = nxt[j]) ++sum;
        if(res == -1 || res > sum) res = sum;
    }
    return res;
}
int main()
{
#ifdef ACM_TEST
    freopen("in.txt", "r", stdin);
#endif
    scanf("%d%d", &n, &m);
    int l = 0, r = 0, mid, ans = 0;
    for(int i = 0; i < n; ++i)
    {
        scanf("%d", &L[i]);
        L[i + n] = L[i];
        l = max(l, L[i]);
        r += L[i];
    }
    while(l <= r)
    {
        mid = (l + r) >> 1;
        if(solve(mid) <= m)
        {
            r = mid - 1;
            ans = mid;
        }
        else
        {
            l = mid + 1;
        }
    }
    printf("%d\n", ans);
    return 0;
}
accuracy: 0.96875
time_ms: 20
memory_kb: 1972
final_rank: 14

code_snippet: #include <bits/stdc++.h>
#define INF 1000000007
#define MP make_pair
#define FI first
#define SE second
#define PB push_back
#define VI vector<int>
const double EPS = 1e-7, PI = acos(-1.0);
using namespace std;
typedef long long LL;
typedef pair <int, int> P;
const int NUM = 100010;
int n, m, L[NUM];
int first[NUM], len[NUM];
int solve(int t)
{
    int res = n, sum = 0, i, j;
    memset(len, -1, sizeof(len));
    for(i = 0; i < n && sum + L[i] <= t; ++i) first[i] = i + 1, sum += L[i], len[i] = 0;
    if(i == n) return 1;
    len[i - 1] = 1;
    first[i - 1] = 0;
    for(j = 0; j < n; ++j)
	{
		sum -= L[j];
		for(;i < n + n && sum + L[i] <= t; ++i)
		{
			sum += L[i];
			len[i] = len[j] + 1;
			first[i] = first[j];
//			cout<<i << ' ' << j <<' ' << len[i] << ' ' << first[i] << endl;
			if(i - first[i] + 1 >= n) res = min(res, len[i]);
		}
	}
    return res;
}
int main()
{
#ifdef ACM_TEST
    freopen("in.txt", "r", stdin);
#endif
    scanf("%d%d", &n, &m);
    int l = 0, r = 0, mid, ans = 0;
    for(int i = 0; i < n; ++i)
    {
        scanf("%d", &L[i]);
        L[i + n] = L[i];
        l = max(l, L[i]);
        r += L[i];
    }
//    l = r = 15;
    while(l <= r)
    {
        mid = (l + r) >> 1;
        if(solve(mid) <= m)
        {
            r = mid - 1;
            ans = mid;
        }
        else
        {
            l = mid + 1;
        }
    }
    printf("%d\n", ans);
    return 0;
}
accuracy: 0.96875
time_ms: 10
memory_kb: 2276
final_rank: 15

code_snippet: //#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<bitset>
#include<time.h>

#define Msn(x,y) (memset((x),0,sizeof((x[0]))*(y+1)))
#define msn(x) (memset((x),0,sizeof((x))))
#define msx(x,y) (memset((x),0x7f,sizeof((x[0]))*(y+3)))
#define fuck(x) cerr << #x << " <- " << x << endl
#define acer cout<<"sb"<<endl
#define mkp(x,y) (make_pair(x,y))
#define fi first
#define se second
#define ture true
#define lch  (id<<1)
#define rch (id<<1|1)

typedef long long ll;
using namespace std;
int n,m;
const int maxn=50007;
int L[maxn*2];
int sum[maxn*2];
int fa[maxn*2][33];
bool check(int k)
{
    msn(fa);
    for(int i=1;i<=2*n-1;i++)
    {
        int l=i,r=2*n-1;
        while(l<r)
        {
            int mid=(l+r)/2+1;
            if(sum[r]-sum[i-1]>k)r=mid-1;
            else l=mid;
        }
        fa[i][0]=l+1;
//        printf("%d %d\n",i,l+1);
    }
    fa[2*n][0]=2*n;
    for(int i=1;i<=20;i++)
    {
        for(int j=1;j<=2*n;j++)
        {
            fa[j][i]=fa[fa[j][i-1]][i-1];
        }
    }
    for(int i=1;i<=n;i++)
    {
        int x=m;
        int v=i;
        int ct=0;
        while(x)
        {
            if(x&1)v=fa[v][ct];
            x>>=1;
            ct++;
        }
//        fuck(v);
        if(v>i+n-1)return 1;
    }
    return 0;
}

int main()
{
    scanf("%d%d",&n,&m);
    int l,r;
    l=0,r=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&L[i]);
        L[i+n]=L[i];
        l=max(L[i],l);
        r+=L[i];
    }
    for(int i=1;i<=2*n;i++)
    {
        sum[i]=sum[i-1]+L[i];
    }
    while(l<r)
    {
        int mid=(l+r)/2;
//        printf("%d %d %d\n",l,mid,r);
//        fuck(check(mid));
//        fuck(check(mid));
        if(check(mid))r=mid;
        else l=mid+1;
    }
    printf("%d\n",l);
    return 0;
}
/*

4 4
1 3 4 2
2 1
1 1
*/
accuracy: 0.03125
time_ms: 10
memory_kb: 14084
final_rank: 18

code_snippet: #include<stdio.h>
#include<algorithm>
using namespace std;
int c[110000];
int sum[110000];
int db[18][110000];
int main(){
	int a,b;scanf("%d%d",&a,&b);
	for(int i=0;i<a;i++){
		scanf("%d",c+i);
	}
	for(int i=0;i<a;i++)c[a+i]=c[i];
	for(int i=0;i<a*2;i++)sum[i+1]=sum[i]+c[i];
	sum[a*2+1]=999999999;
	int left=0;
	int right=100000000;
	while(left+1<right){
		int M=(left+right)/2;
		for(int i=0;i<a*2;i++){
			db[0][i]=upper_bound(sum,sum+a*2+1,sum[i]+M)-sum-1;
		}
	//	printf("%d\n",M);
	//	for(int i=0;i<a*2;i++)printf("%d ",db[0][i]);printf("\n");
		db[0][a*2]=a*2;
		for(int i=1;i<18;i++){
			for(int j=0;j<=a*2;j++){
				db[i][j]=db[i-1][db[i-1][j]];
			}
		}
		bool ok=false;
		for(int i=0;i<a;i++){
			int at=i;
			for(int j=0;j<18;j++){
				if(b&(1<<j)){
					at=db[j][at];
				}
			}
			if(at>=i+a)ok=true;
		}
		if(ok)right=M;else left=M;
	}
	printf("%d\n",right);
}
accuracy: 1
time_ms: 190
memory_kb: 9440
final_rank: 9

code_snippet: #include <iostream>
#include <cstdio>
#include <vector>
#include <list>
#include <cmath>
#include <fstream>
#include <algorithm>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <complex>
#include <iterator>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <stack>
#include <climits>
#include <deque>
#include <bitset>
#include <cassert>
#include <ctime>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
//const int dy[]={-1,0,1,0},dx[]={0,1,0,-1};
// adjust problem by problem
const double EPS=1e-8;
const double PI=acos(-1.0);
#ifdef __GNUC__
int popcount(int n){return __builtin_popcount(n);}
int popcount(ll n){return __builtin_popcountll(n);}
#endif
#ifndef __GNUC__
template<class T> int popcount(T n){int cnt=0;while(n){if(n%2)cnt++;n/=2;}return cnt;}
#endif
template<class T>int SIZE(T a){return a.size();}
template<class T>string IntToString(T num){string res;stringstream ss;ss<<num;return ss.str();}
template<class T>T StringToInt(string str){T res=0;for(int i=0;i<SIZE(str);i++)res=(res*10+str[i]-'0');return res;}
template<class T>T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template<class T>T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> void PrintSeq(T &a,int sz){for(int i=0;i<sz;i++){cout<<a[i];if(sz==i+1)cout<<endl;else cout<<' ';}}
bool EQ(double a,double b){return abs(a-b)<EPS;}
void fastStream(){cin.tie(0);std::ios_base::sync_with_stdio(0);}
vector<string> split(string str,char del){
  vector<string> res;
  for(int i=0,s=0;i<SIZE(str);i++){
    if(str[i]==del){if(i-s!=0)res.push_back(str.substr(s,i-s));s=i+1;}
    else if(i==SIZE(str)-1){res.push_back(str.substr(s));}
  }
  return res;
}
int N,M;
int L[100001];
int nexts[17][50001];

void calcNext(int X){
  memset(nexts,-1,sizeof(nexts));
  int tail=0;
  int sum=0;
  // if(X==4){
  //   cout<<endl;
  // }
  for(int head=0;head<N;head++){
    //sum+=L[head];
    while(tail<N){
      sum+=L[tail];
      if(sum>X){
        sum-=L[tail];
        break;
      }
      tail++;
    }
    nexts[0][head]=tail;
    sum-=L[head];
  }
  for(int i=1;i<17;i++){
    for(int j=0;j<N;j++){
      if(nexts[i-1][j]==-1)nexts[i][j]=-1;
      else nexts[i][j]=nexts[i-1][nexts[i-1][j]];
    }
  }
}

// [from,to]の範囲の数字をM-1個でoverlapできるか？
int isOverLap(int from,int to){
  int num=M-1;
  int pos=from;
  for(int i=0;num>0;i++){
    if(num%2)pos=nexts[i][pos];
    if(pos==-1)break;
    num/=2;
  }
  return (pos==-1||to<pos);
}

bool check(int X){
  if(M==1){
    int sum=0;
    for(int i=0;i<N;i++)sum+=L[i];
    return (sum<=X);
  }
  else{
    int head=0;
    int tail=0;
    int sum=L[0];
    tail=N-1;
    while(tail!=head){
      sum+=L[tail];
      if(sum>X){
        sum-=L[tail];
        break;
      }
      tail--;
    }
    if(tail==head){
      return true;
    }
    else{
      //tail++;
      // それぞれの場所から
      // 2^0,2^1,2^2,2^3,...個先へ行った場所が何になるかを計算
      // if(X==4){
      //   cout<<endl;
      // }
      calcNext(X);
      //tail++;
      while(tail<N){
        while(1){
          head++;
          if(sum+L[head]>X){
            head--;
            break;
          }
          sum+=L[head];
        }
        if(isOverLap(head+1,tail))return true;
        tail++;
        if(tail==N)break;
        sum-=L[tail];
      }
    }
  }
  return false;
}

void solve(){
  //ifstream cin("in.txt");
  cin>>N>>M;
  for(int i=0;i<N;i++)cin>>L[i];
  int lb=0;
  int ub=0;
  for(int i=0;i<N;i++){
    lb=max(lb,L[i]);
    ub+=L[i];
  }
  lb--;
  while(ub-lb>1){
    int mid=(ub+lb)/2;
    if(check(mid))ub=mid;
    else lb=mid;
  }
  cout<<ub<<endl;
}

int main(){

  solve();
  
  return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 4692
final_rank: 8

code_snippet: #include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>
#include <numeric>

using namespace std;

#define FOR(i,k,n) for(int i=(k); i<(int)(n); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int N, M;
vector<int> L;
bool ok(int X){
  int firstsum = 0; // add L[0], L[1], ..., L[b - 1] to last block
  for(int b = 0; b < N; b++){ // begin index of first block
    if(firstsum > X) break;
    int rest = M; // rest of blocks
    int partial = 0; // sum of current block
    for(int i = b; i < N; i++){
      partial += L[i];
      if(partial > X){ // use next block
        partial = L[i];
        rest --;
        if(rest <= 0) break; // block shortage
      }
    }
    if(rest > 0 && partial + firstsum <= X) return true; // last block is not overflow

    firstsum += L[b]; // add L[b] to last block
  }
  return false;
}

int main(){
  while(cin>>N>>M && N){
    L.assign(N, 0);
    REP(i, N) scanf("%d", &L[i]);
    int S = accumulate(L.begin(), L.end(), 0);
    int lb = ceil(double(S) / M) - 1; // answer >= ceil(S / M)
    REP(i, N) lb = max(lb, L[i] - 1); // answer >= max(L[i])
    int ub = S; // answer <= S
    while(ub - lb > 1){
      int mid = (ub + lb) / 2;
      if(ok(mid)){
        ub = mid;
      }else{
        lb = mid;
      }
    }
    cout<<ub<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 640
memory_kb: 1288
final_rank: 3

code_snippet: #include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>
#include <numeric>

using namespace std;

#define FOR(i,k,n) for(int i=(k); i<(int)(n); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)

template<class T> void debug(T begin, T end){ for(T i = begin; i != end; ++i) cerr<<*i<<" "; cerr<<endl; }
inline bool valid(int x, int y, int W, int H){ return (x >= 0 && y >= 0 && x < W && y < H); }

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
/*
bool ok(vector<int>& L, int X){
  int idx = L.size();
  int first = 0;
  while(true){
    int cnt = 1;
    int now = first;
    bool ok = true;
    REP(i, idx){
      if(now + L[i] <= X){
        now += L[i];
      }else{
        now = L[i];
        cnt++;
      }
      if(cnt > M || now > X){
        ok = false;
        break;
      }
    }
    if(ok) return true;

    idx--;
    assert(idx >= 0);
    first += L[idx];
    if(first > X) break;
  }
  return false;
}
*/
int N, M;
vector<int> L;
bool ok(int X){
  int firstsum = 0; // add L[0], L[1], ..., L[b - 1] to last block
  for(int b = 0; b < N; b++){ // begin index of first block
    if(firstsum > X) break;
    int rest = M; // rest of blocks
    int partial = 0; // sum of current block
    for(int i = b; i < N; i++){
      partial += L[i];
      if(partial > X){ // use next block
        partial = L[i];
        rest --;
        if(rest <= 0) break; // block shortage
      }
    }
    //printf("rest = %d partial = %d firstsum = %d X = %d\n", rest, partial, firstsum, X);
    if(rest > 0 && partial + firstsum <= X) return true; // last block is not overflow

    firstsum += L[b]; // add L[b] to last block
  }
  return false;
}

int main(){
  while(cin>>N>>M && N){
    L.assign(N, 0);
    REP(i, N) scanf("%d", &L[i]);
    int S = accumulate(L.begin(), L.end(), 0);
    int lb = ceil(double(S) / M) - 1; // answer >= ceil(S / M)
    REP(i, N) lb = max(lb, L[i] - 1); // answer >= max(L[i])
    int ub = S; // answer <= S
    while(ub - lb > 1){
      int mid = (ub + lb) / 2;
      if(ok(mid)){
        ub = mid;
      }else{
        lb = mid;
      }
    }
    cout<<ub<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 640
memory_kb: 1288
final_rank: 3

code_snippet: #include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>
#include <numeric>

using namespace std;

#define FOR(i,k,n) for(int i=(k); i<(int)(n); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)

template<class T> void debug(T begin, T end){ for(T i = begin; i != end; ++i) cerr<<*i<<" "; cerr<<endl; }
inline bool valid(int x, int y, int W, int H){ return (x >= 0 && y >= 0 && x < W && y < H); }

typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
/*
bool ok(vector<int>& L, int X){
  int idx = L.size();
  int first = 0;
  while(true){
    int cnt = 1;
    int now = first;
    bool ok = true;
    REP(i, idx){
      if(now + L[i] <= X){
        now += L[i];
      }else{
        now = L[i];
        cnt++;
      }
      if(cnt > M || now > X){
        ok = false;
        break;
      }
    }
    if(ok) return true;

    idx--;
    assert(idx >= 0);
    first += L[idx];
    if(first > X) break;
  }
  return false;
}
*/
int N, M;
vector<int> L;
bool ok(int X){
  REP(i, N) if(L[i] > X) return false;

  int firstsum = 0;
  for(int b = 0; b < N; b++){
    if(firstsum > X) break;
    int rest = M - 1;
    int partial = 0;
    for(int i = b; i < N; i++){
      if(partial + L[i] > X){
        partial = L[i];
        assert(partial <= X);
        rest --;
      }else{
        partial += L[i];
      }
    }
    //printf("rest = %d partial = %d firstsum = %d X = %d\n", rest, partial, firstsum, X);
    if(rest >= 0 && partial + firstsum <= X) return true;

    firstsum += L[b];
  }
  return false;
}

int main(){
  while(cin>>N>>M && N){
    L.assign(N, 0);
    REP(i, N) scanf("%d", &L[i]);
    int S = accumulate(L.begin(), L.end(), 0);
    int lb = ceil(double(S) / M) - 1;
    int ub = S;
    while(ub - lb > 1){
      int mid = (ub + lb) / 2;
      if(ok(mid)){
        ub = mid;
      }else{
        lb = mid;
      }
    }
    cout<<ub<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 640
memory_kb: 1284
final_rank: 2

code_snippet: #include <cstdio>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;

int n, m;
vector<int> sum;


int check(int x, int mid){
	int t = x;
	int mindif = INT_MAX;
	int minindex = -1;

	for(int k = 0; k < m; ++k){
		int u = upper_bound(sum.begin(), sum.end(), sum[t] + mid)
				 - sum.begin() - 1;

		if(mindif > u - t){
			mindif = u - t;
			minindex = t;
		}

		t = u;
		if(t - x >= n){
			return minindex;
		}
	}
	return -1;
}


int binsearch(int x, int left, int right){
	while(left < right){
		int mid = (left + right) / 2;
		if( check(x, mid) >= 0 ){
			right = mid;
		}
		else{
			left = mid + 1;
		}
	}
	return left;
}


int main(){
	scanf("%d%d", &n, &m);
	vector<int> L(n);
	for(int i = 0; i < n; ++i){
		scanf("%d", &L[i]);
	}

	sum.resize(3 * n + 1);
	int k = 0;
	for(int i = 0; i < 3; ++i)
	for(int j = 0; j < n; ++j){
		sum[k+1] = sum[k] + L[j];
		++k;
	}

	k = binsearch(0, 1, sum[n]);
	int upb = k;
	int from = check(0, upb);

	for(int i = from; sum[i] - sum[from] <= k; ++i){
		upb = binsearch(i, 1, upb);
	}
	
	printf("%d\n", upb);
}
accuracy: 1
time_ms: 90
memory_kb: 1796
final_rank: 1