题解:思路很奇妙,不太好想。
这道题可以通过二分来解决,每次要么往左移动要么往右移动,反正不可以不动。假设二分到答案x,那么
对arr[i]这个数,我们至少要来x%arr[i] ? x/arr[i]+1 : x/arr[i]这么多次,所以说我们可以通过左右移动来不断的来使得arr[i]达到要求,当来arr[i] a次时,必须去arr[i+1] 或者说arr[i-1] a-1次,这里(我们处理为都右->左->右->左)。也就是说当我们来arr[i] a次时,arr[i+1]来了a-1次。所以当为们考虑第i个位置时,当完成第i-1个位置时已经帮arr[i]完成了一部分....具体实现看代码吧:
#include<bits/stdc++.h> using namespace std; const long long N=1e5+7; long long arr[N]; long long num[N]; long long n,m; bool check(long long x){ long long tmp=0; long long tmpnext=0; long long sum=0; for(long long i=1;i<=n;i++){ tmp=x/arr[i]; if(x%arr[i]) tmp++; tmp-=tmpnext;//这里的tmpext还没有更新,所以表示的是在完成i-1的时候完成i的部分。 if(tmp<=0) {//说明第i个点在第i-1的时候已经被完成了。 if(i!=n) tmp=1;//每次都得移动一个 else tmp=0;//到达n了,并且n也满足了,怎么着都无所谓了 tmpnext=0; } else tmpnext=tmp-1; sum+=tmp+tmpnext; if(sum>m) return false; } return 1; } int main(){ cin>>n>>m; for(long long i=1;i<=n;i++) cin>>arr[i]; long long l=0; long long r=1e18+7; long long ans=0; while(l<=r){ long long mid=(r+l)/2; if(check(mid)){ l=mid+1; ans=max(ans,mid); } else r=mid-1; } cout<<ans<<endl; return 0; }