一开始对每个i位置查最接近m的区间时,从0扫到刚好大于等于m的位置,这样有个case超时了。然后想了下,前缀和是有序的,而我们必然可以从0~i这区间找到一个位置j使得pre[i] - pre[j] >= m,因此想到二分。
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int n;
long long m;
long long pre[100005];
vector<pair<int, int> > ans;
int find(int x, int y){
int left = x, right = y;
int mid;
while(left < right){
// cout << left << " " << right << endl;
mid = (left + right) / 2;
if(pre[y] - pre[mid] < m){
right = mid;
}
else if(pre[y] - pre[mid] > m)
left = mid + 1;
else
return mid;
}
return (left + right) / 2 - 1;
}
int main(){
scanf("%d %lld",&n,&m);
pre[0] = 0;
for(int i = 1; i <= n; ++i){
scanf("%lld",&pre[i]);
pre[i] += pre[i-1];
}
long long min_div = 100000005;
for(int i = 1; i <= n; ++i){
if(pre[i] >= m){
int j = find(0,i);
// cout << j << endl;
if(pre[i] - pre[j] - m < min_div){
min_div = pre[i] - pre[j] - m;
ans.clear();
ans.push_back(make_pair(j+1,i));
}
else if(pre[i] - pre[j] - m == min_div){
ans.push_back(make_pair(j+1,i));
}
}
}
// cout << ans.size()<<endl;
for(int i = 0; i < ans.size(); ++i){
printf("%d-%d\n",ans[i].first,ans[i].second);
}
return 0;
}