C,zoj4062
最小值最大化,典型的二分答案
关键是judge函数怎么写
除此之外,写出judge也很难ac,此题尽是坑点,写的我一把辛酸泪啊QAQ~~
什么最后一个要特判,不加次数。。
什么很容易超ll。。
什么负数。。
什么超时。。
都要及时跳出才行
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 typedef long long ll; 6 const int maxn=1e5+10; 7 8 int n; 9 ll m; 10 ll a[maxn],d[maxn]; 11 12 ll judge(ll k) 13 { 14 //memset(d,0,(n+1)*sizeof(ll)); 15 //memset(d,0,sizeof(d));//1520ms 16 for(int i=0;i<=n+1;i++) d[i]=0;//630ms 17 18 ll cnt=0; 19 for(int i=1;i<=n;i++) 20 { 21 if(i==n && d[i]>=k) break;//坑点1,最后一个特判 22 23 cnt++; d[i]+=a[i];//注意这个细节,d[i]+=a[i]要放到continue前面,后面必错!(先把每一步必须的一步加上,不要和后面的放在一起算,不容易错) 24 if(d[i]>=k) continue;//坑点2,不要一直加,会超ll,同时关键防止了下面负数情况!! 25 //d[i]+=a[i];//之前以为放这一直错QAQ 26 27 ll c=(k-d[i])/a[i];//坑点3,这里(通过上面continue)要防止了过大变负数 28 if((k-d[i])%a[i]) c++; 29 cnt+=2*c; 30 d[i]+=c*a[i]; 31 d[i+1]+=c*a[i+1]; 32 33 if(cnt>m) break; 34 } 35 return cnt; 36 } 37 38 int main() 39 { 40 ios::sync_with_stdio(0); 41 cin.tie(0); 42 43 int T; 44 cin>>T; 45 while(T--) 46 { 47 cin>>n>>m; 48 ll mn=1e5+10; 49 for(int i=1;i<=n;i++) cin>>a[i], mn=min(mn,a[i]); 50 51 ll l=0, r=mn*m,ans=0; 52 while(l<=r) 53 { 54 ll mid=(l+r)>>1; 55 if(judge(mid)<=m) 56 { 57 ans=mid; 58 l=mid+1; 59 } 60 else r=mid-1; 61 } 62 cout<<ans<<endl; 63 } 64 }
完。