T1:P1182T1:P1182 数列分段SectionIISectionII
评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P1182
大意
有n个数,要求分成m段使每段的和之中的最大值最小。
解题思路
二分最大值,然后枚举过去看至少分成几段。然后利用答案二分。
code
#include<cstdio>
using namespace std;
int n,m,a[100001],l,r,mid;
bool check(int x)//判断答案
{int sum=0,k=0;for(int i=1;i<=n;i++)if (a[i]>x) return false;else if (sum+a[i]>x) k++,sum=a[i];else sum+=a[i];return k<m;
}
int main()
{scanf("%d%d",&n,&m);for (int i=1;i<=n;i++)scanf("%d",&a[i]),r+=a[i];l=1;while (l<=r)//二分答案{mid=(l+r)>>1;if(check(mid)) r=mid-1;else l=mid+1;}printf("%d",l);
}
T2:P1873T2:P1873 砍树
评测记录:https://www.luogu.org/problemnew/show/P1873
正题
有n棵,需要m个木材,每个木头有不同的高度,选择一个高度,可以获得m个木材时高度最高。
解题思路
直接二分高度。
code
#include<cstdio>
#include<iostream>
using namespace std;
int n,m,lef,righ,mid,a[1000001];
long long countt;
int main()
{scanf("%d%d",&n,&m);for (int i=1;i<=n;i++) {scanf("%d",&a[i]); righ=max(a[i],righ);}lef=0;while (lef<righ){countt=0;mid=(lef+righ+1)/2;//二分答案for (int i=1;i<=n;i++) countt+=max(a[i]-mid,0);//统计答案if (countt<m) righ=mid-1;else lef=mid;}printf("%d",lef);
}