二分法初次嘗試
//刷二分法的第一道題目,搞懂它搞了3個多小時,惡補了二分法的基礎上終於理解了,不容易,欲速則不達,必須具備相應的基礎,否則過於生硬。
#include<iostream>
#include<cstdio>
using namespace std;
int a[1000000];
int judge(int mid,int a[],int n,int m)
{
int i;
int sum=0;
int t=1;//這裡初值寫成了t=0,實際下面的操作中導致了少算了一次。
for(i=1;i<=n;i++)
{
if(a[i]+sum>mid)
{
sum=a[i];
t++;
}
else sum=sum+a[i];
}
if(t>m)
return 1;
else return 0;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
int i;
int maxn=0,total=0;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]>maxn)
maxn=a[i];
total+=a[i];
}
int l=maxn;
int r=total;
int mid;
while(l<=r)
{
mid=(l+r)/2;
if(judge(mid,a,n,m))l=mid+1;
else r=mid-1;
}
cout<<l<<endl;//,這裡錯了,寫成了mid這裡需要考慮的是最後一次是l與r相等的情況下,下一次就結束了,所以是最後一次了,這時候如果返回的次數正好多餘要求的次數即返回1的情況下,
//我們需要回到正好的狀態就是讓l+1,這個相當於是一個回溯的操作,即尋找可能性失敗後的回退機制,所以這裡是輸出l,當然如果最後r與l相等的情況下
//如果返回的仍然是0,這個時候就是最佳狀態了,返回mid和l是一樣的。(以上分析錯誤的原因主要是二分法操作不熟練導致,欲速不達,二分法必須熟練掌握才能
//完全解決各種的子段最少的最大題。)
return
}