poj 3061 Subsequence(二分/双指针)
题目链接:http://poj.org/problem?id=3061
题意
在 n 个元素的数组中寻找和不小于 s 的最短连续区间。
思路
思路一
作前缀和二分查找,时间复杂度 $O_{(nlogn)}$ 。
代码一
#include <cstdio> #include <algorithm> using namespace std; const int M = 1e5 + 100; int a[M], sum[M]; void solve() { int n, s; scanf("%d%d", &n, &s); for (int i = 0; i < n; i++) scanf("%d", &a[i]); for (int i = 0; i < n; i++) sum[i + 1] = sum[i] + a[i]; if (sum[n] < s) { puts("0"); return; } int res = n; for (int i = 0; sum[i] + s <= sum[n]; i++) { int j = lower_bound(sum + i, sum + n, sum[i] + s) - sum; res = min(res, j - i); } printf("%d\n", res); } int main() { int t; scanf("%d", &t); while (t--) solve(); }
思路二
双指针,在保证指针区间的和不小于 s 的同时每次删减最左端的元素,时间复杂度 $O_{(n)}$ 。
代码二
#include <cstdio> #include <algorithm> using namespace std; const int M = 1e5 + 100; int a[M], sum[M]; void solve() { int n, s; scanf("%d%d", &n, &s); for (int i = 0; i < n; i++) scanf("%d", &a[i]); int res = n + 1; for (int l = 0, r = 0, sum = 0;;) { while (r < n and sum < s) { sum += a[r++]; } if (sum < s) break; res = min(res, r - l); sum -= a[l++]; } if (res > n) { puts("0"); return; } printf("%d\n", res); } int main() { int t; scanf("%d", &t); while (t--) solve(); }