比赛的时候这题的题意一直没看懂,后面才明白意思就是有n个物品,然后要求最多可以挑选出多少物品,挑选过程是从第一给物品开始往右边挑选,对于每一个物品,如果目前的盒子剩余空间是>=该物品的体积的就直接放进盒子,继续挑选下一个物品,若目前的盒子剩余空间是<该物品的体积的,那就要另外开一个盒子来放物品了,若目前已经没有可用的盒子了,说明这次选取是非法的,那么之前选取的所有物品都不可以得到,然后就把选取的第一个物品退回去,看是否有剩余的空间放下该物品,如果还是放不下的话,继续把第二个拿的物品退回去,直至可以放下该物品为止,然后继续选取下去,若目前还有可用的盒子,那就继续选取下去。选取物品的终点是把最后一个物品也选取了,这样的选取才是合法的,那么盒子的选取的物品的数量的最大值即是我们要的,这个过程可以看出是依次从第1个至第n个物品开始选取物品,若可以把最后一个也选了,那就更新答案,但是这样的话复杂度2e5*2e5是会超时的,然后可以发现起点越大挑选成功的可能性越大,具有单调性,因此可以用二分。
#include<bits/stdc++.h>
using namespace std;
#define fuck(x) cout<<#x<<" "<<x<<endl;
const int maxn=2e5+10;
int n,m,k,a[maxn];
bool check(int mid)
{
int rp=k,num=1;
for(int i=mid;i<=n;i++)
{
if(rp>=a[i])
{
rp-=a[i];
}
else
if(num<m)
{
num++;
rp=k-a[i];
}
else
return false;
}
return true;
}
int main()
{
scanf("%d %d %d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&(a[i]));
}
int low=1,high=n,mid,ans=0;
while(low<=high)
{
mid=(low+high)/2;
if(check(mid))
{
ans=max(ans,n-mid+1);
high=mid-1;
//fuck(mid);
}
else
low=mid+1;
}
printf("%d\n",ans);
return 0;
}