一、思路
即求:相加为大于M的最小和的所有连续子串,且要求复杂度o(n),否则会出现测试点超时;
思路:
一趟遍历无回溯,l和r表示当前子串左右边界,sum为子串和,min为当前最小子串和;
若sum>=m,若同时sum==min,则{l, r}是一组解,若sum<min,则应更新min并清空之前的解(已不是最优解);
然后l左边界进位;
若sum<m,则说明子串太短,应有r右边界进位;
核心代码:
for( int l = 0, r = 0, sum = val[0], min = 0x7FFFFFFF; r < N; )
if( sum >= M )
{
if( sum < min )
{
min = sum;
ans.clear();
}
if( sum == min )
ans.push_back({l + 1, r + 1});
sum -= val[l++];
}
else sum += val[++r];
二、代码
#include <cstdio>
#include <vector>
#include <utility>
using namespace std;
int main()
{
int N, M;
scanf("%d %d", &N, &M);
vector<int> val(N);
vector<pair<int, int>> ans;
for( int i = 0; i < N; ++i )
scanf("%d", &val[i]);
for( int l = 0, r = 0, sum = val[0], min = 0x7FFFFFFF; r < N; )
if( sum >= M )
{
if( sum < min )
{
min = sum;
ans.clear();
}
if( sum == min )
ans.push_back({l + 1, r + 1});
sum -= val[l++];
}
else sum += val[++r];
for( int i = 0; i < ans.size(); ++i )
printf("%d-%d\n", ans[i].first, ans[i].second);
}