Note
- for循环嵌套二分查找
- 打印需要按照i增加的顺序,因此用外层for循环 (i递增) ,内层用二分查找 (降低时间复杂度) 。
- 因为读入的数组是递增顺序,所以考虑到了二分查找
- 二分查找的下界left=i ,上界right=n 。v[mid]-v[i-1]找大了就往左边[left,mid-1]找;反之往右边[mid+1,right]找。
- 错点:外层for循环的i可以取到n;参考样例"11-11"的情况。
Code:
#include<bits/stdc++.h>
using namespace std;
int main(){
#ifndef ONLINE_JUDGE
freopen("data.txt","r",stdin);
#endif
int n,m;
cin>>n>>m;
int v[n+1];
memset(v,0,sizeof(v));
for(int i=1;i<=n;i++){
cin>>v[i];
v[i]+=v[i-1];
}
int left,right,mid;
int min=999999999;
//int minans = sum[n]; //柳神:直接用总和初始化min
vector<int> index;
for(int i=1;i<=n;i++){ //i可以取到n!!!
left=i,right=n;
while(left<=right){ //for嵌套二分查找 降低时间复杂度
mid=(left+right)/2;
if(v[mid]-v[i-1]==m){
min=0;
printf("%d-%d\n",i,mid);
break;
}
else if(v[mid]-v[i-1]>m){
if(min!=0){
if(min>(v[mid]-v[i-1])){
index.clear();
min=v[mid]-v[i-1];
index.push_back(i);
index.push_back(mid);
}
else if(min==(v[mid]-v[i-1])){
index.push_back(i);
index.push_back(mid);
}
}
right=mid-1;
}
else left=mid+1;
}
}
if(min>0){
for(int i=0;i<index.size();i+=2)
printf("%d-%d\n",index[i],index[i+1]);
}
return 0;
}