PAT A1044
解题思路:
- 数组sum[i]:a[1]+a[2]+…+a[i];严格单调增加。
- 所以本题就变为寻找sum[j]-sum[i]等于定值或略大于定值时i,j的值,然后输出i,j。
- upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
- lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
- 使用upper_bound注意查找到的p值需回退一个判别是否等于给定值;
upper_bound
#include<cstdio>
#include<algorithm>
using namespace std;
int n,total;
int sum[100010];
int main(){
sum[0]=0;
int ans=999999;
scanf("%d %d",&n,&total);
for(int i=1;i<=n;i++){
scanf("%d",&sum[i]);
sum[i]+=sum[i-1];
}
for(int i=1;i<=n;i++){
int p=upper_bound(&sum[i],&sum[n]+1,sum[i-1]+total)-&sum[1];
if(sum[p]-sum[i-1]==total){
ans=total;
break;
}else if(p<=n-1){
ans=min(sum[p+1]-sum[i-1],ans);
}
}
for(int i=1;i<=n;i++){
int p=upper_bound(&sum[i],&sum[n]+1,sum[i-1]+ans)-&sum[1];
if(sum[p]-sum[i-1]==ans){
printf("%d-%d\n",i,p);
}
}
}
lower_bound
#include<cstdio>
#include<algorithm>
using namespace std;
int n,total;
int sum[100010];
int main(){
sum[0]=0;
int ans=999999;
scanf("%d %d",&n,&total);
for(int i=1;i<=n;i++){
scanf("%d",&sum[i]);
sum[i]+=sum[i-1];
}
for(int i=1;i<=n;i++){
int p=lower_bound(&sum[i],&sum[n]+1,sum[i-1]+total)-&sum[0];
if(sum[p]-sum[i-1]==total){
ans=total;
break;
}else if(p<=n){
ans=min(sum[p]-sum[i-1],ans);
}
}
for(int i=1;i<=n;i++){
int p=lower_bound(&sum[i],&sum[n]+1,sum[i-1]+ans)-&sum[0];
if(sum[p]-sum[i-1]==ans){
printf("%d-%d\n",i,p);
}
}
}