P1182 数列分段 Section II
链接:P1182
---------------------------------------
一道一眼就能看出来的二分题,而且深刻让我感受到了什么叫不开long long 一场空
(因为这个卡了我半个小时QWQ)
---------------------------------------
思路还是两部分,二分部分是模板,没什么好说的。
check部分就是定义一个flag记录上一个段的结尾地址,然后用前缀和计算区间和,如果比mid大,
就更新flag,并且段数++,然后继续。
最后和m比一下,返回值真假,继续二分
---------------------------------------
#include<iostream> #include<cstdio> using namespace std; const int maxn = 100000+5; long long sum[maxn*10]; long long num[maxn*10]; int n,m; bool check(long long f){ int flag=0; int cnt=0; int ans=0; for(int i=1;i<=n;++i){ ans=sum[i]-sum[flag]; if(ans>f){ cnt++; flag=i-1; ans=0; continue; } } if(cnt>=m) return 1; else return 0; } int main(){ long long l=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i){ scanf("%lld",&num[i]); sum[i]=(sum[i-1]+num[i]); l=max(l,num[i]); } long long r=sum[n]; long long mid; while(l<=r){ mid=(l+r)/2; if(check(mid)) l=mid+1; else r=mid-1; } cout<<l; return 0; }