原题链接:Subsequence - UVALive 2678 - Virtual Judge
题意:由n个正整数组成的一个序列,给定整数S,求长度最短的连续序列,使他们的和大于等于S。(1<=n<=10^5,S<10^9)
前缀和是要求的
后面有两种方法
(1)顺i找j
(2)顺j找i
详细内容在代码注释里写了
多理解多思考
一定要注意细节,很容易错
#include<iostream>
#include<cstring>
using namespace std;
const int N = 100010;
int a[N];
int b[N];
int main() {
int n, s;
while (cin >> n >> s) {
for (int i = 1; i <= n; i++) {
cin >> a[i];
b[i] = b[i - 1] + a[i]; //前缀和
}
//这里把i看成原来的i-1
//顺i找j
// 这里用的是单调队列的思想
// 每次满足了条件,就把队头删掉,然后往后进队,直到下次满足条件
// 如果到了最后一个值进队还满足不了条件,说明后面都满足不了条件了
//int j = 1;
//int ans = n + 1;
//for (int i = 0; i < n; i++) {
// while (j <= n &&b[j] - b[i] < s) j++;
// if (j == n + 1) break;
// if (j - i < ans) ans = j - i;
//}
//顺j找i
//这里用的是分析计算公式
//bj - bi >= s --> bi <= bj - s;
//j增加的时候,bi也增加,而b本来就是单增的,所以i也单增
int i = 0;
int ans = n + 1;
for (int j = 1; j <= n; j++) {
if (b[i] > b[j] - s) continue; //不可能了,增加j
while (b[i] <= b[j] - s) i++;
ans = min(ans, j - i + 1);
}
ans = ans == n + 1 ? 0 : ans;
cout << ans << endl;
}
return 0;
}