二分的思路是想出来了的啊,就是又被二分的边界搞心态了
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题意就是在数组中找三段数组,其中中间的数组总值最大,问一共有多少组
比赛中的代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
int n;
cin>>n;
vector<int>v(n+1),pri(n+1,0);
for(int i=1;i<=n;i++){
cin>>v[i];
pri[i]=pri[i-1]+v[i];
}
int ans=0;
for(int i=2;i<=n-1;i++){//二分范围[i,n-1]
//pri[i-1],pri[mid]-pri[i-1],pri[n]-pri[mid]
int l=i-1,r=n;
//l=i,r=n-1 这样我觉得是对的
while(l<r){
int mid=(l+r)/2;
if(pri[mid]-pri[i-1]>pri[i-1] && pri[mid]-pri[i-1]>pri[n]-pri[mid]){
r=mid;
ans++;
}
else{//不满足,中间的小了
l=mid+1;
}
}
}
cout<<ans<<endl;
return 0;
}
正确代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main()
{
int n;
cin>>n;
vector<int>v(n+1),pri(n+1,0);
for(int i=1;i<=n;i++){
cin>>v[i];
pri[i]=pri[i-1]+v[i];
}
int cnt=0;
for(int i=1;i<=n-2;i++){
int l=i+1,r=n-1,ans=-1;
int a1=pri[i];
while(l<=r){//如果l==r且为正确答案则记录,若l<r 则记录不到
int mid=(l+r)>>1;
int a2=pri[mid]-pri[i],a3=pri[n]-pri[mid];
if(a2>a1 && a2>a3){
ans=mid;//记录答案
r=mid-1;//为了寻找最左边的答案,此时记录了可能的最左边答案记录了,继续二分看左边是否还有更优答案
}
else{
l=mid+1;
}
}
if(ans!=-1) cnt+=(n-1)-ans +1;
}
cout<<cnt<<'\n';
return 0;
}
正解是个整数二分,答案范围是[i+1,n-1]。如果i满足山峰条件,则i+1一定满足,所以为了找到完整的答案区间,就是要二分到左边第一个满足山峰条件的位置ans,这样ans到n-1都是满足的。
所以就是个寻找最左边。
其中的细节 while(l<=r) , ans=mid,r=mid-1 在代码中详细注释了,至于为什么不是(l+r+1)>>1有待思考。
二分查找边界详解
1056

被折叠的 条评论
为什么被折叠?



