思路:
对这个序列设置两个标志位,left
与right
用twopoint的思想,使整体复杂度为O(n).
AC代码
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 100010;
const int INF = 100000010;
int n,m, a[maxn], sum = 0, min_sum = INF;
int left = 1 , right = 1;
// *****此部分为创建路径path, 并用Add函数添加路径(left,right)****
struct node
{
int left, right;
};
vector<node> path;
void Add(int left, int right){
node x;
x.left = left;
x.right = right;
path.push_back(x);
}
//**********************************************
int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++){
scanf("%d",&a[i]);
}
sum = a[1];
while(left <= n){
while(sum<m && right<n){ //sum <m 右端不断累加
right++;
sum += a[right];
}
if(sum<m){ //说明右端已经到头了但依旧不够付款,break算法结束
break;
}
else{
if(sum < min_sum){ //发现一段更优序列 更新数据 特别是path要先清空再更新
min_sum = sum;
path.clear();
Add(left, right);
}
else if(sum == min_sum){ //发现一段等效序列 加入path
Add(left, right);
}
sum -= a[left]; //左端点+1, 当前序列sum更新
left ++;
}
}
for(int i=0; i<path.size(); i++){
printf("%d-%d\n",path[i].left, path[i].right );
}
return 0;
}