1.用前缀和存储价值
2.二分查找(upper_bound)某一位置开始 前缀和差大于 m-1 的位置(即可能大于等于m)
3.判断是否有刚好等于m的 无 则存储最小近似值
4.计算
在从小到大的排序数组中,
lower_bound( begin,end,num):
从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num):
从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
在从大到小的排序数组中,重载lower_bound()和upper_bound()
lower_bound( begin,end,num,greater<type>() ):
从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num,greater<type>() ):
从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
#include<iostream>
#include<cstring>
#include<vector>
#include<map>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 1e5+5;
int n, m, tmp;
int Sum[N];
int main() {
for(int i=0; i<=N; i++) {
Sum[i] = 0;
}
cin >> n >> m;
for(int i=0; i<n; i++) {
cin >> tmp;
Sum[i+1] = Sum[i]+tmp;
}
int As=Sum[n];
for(int i=0; i<=n; i++) {
int j = upper_bound(Sum+i+1, Sum+n+1, Sum[i]+m-1)-Sum;
if(Sum[j]-Sum[i] == m) {
As = m;
break;
} else if(j <=n)As = min(As, Sum[j]-Sum[i]);
}
for(int i=0; i<=n; i++) {
int j = upper_bound(Sum+i+1, Sum+n+1, Sum[i]+m-1)-Sum;
if(Sum[j]-Sum[i] == As) {
printf("%d-%d\n", i+1, j);
}
}
return 0;
}