Poj3061 Subsequence
July 2, 2016
POJ
Problem
Solution
方法一:O(nlogn)
1. 计算前序和
2. 定起点,二分找不小于S的最小的连续区间和
方法二:O(n)
1. 定起点,线性找不小于S的最小的连续区间和,得到一个终点
2. 把起点向右移动一个单位,把终点在原来的基础上递增,线性找不小于S的最小的连
续区间和。如此反复。
Code
方法一:
C++
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int N, S;
vector<int> a, presum;
void solve() {
cin >> N >> S;
presum.clear();
a.clear();
a.reserve(N);
presum.reserve(N + 1);
for (int i = 0; i < N; ++i) {
int tmp;
cin >> tmp;
a.push_back(tmp);
}
// presum[i] means sum of [0, i) elements
// j > i, presum[j] - presum[i] means sum of [i, j) elements
presum.push_back(0);
for (int i = 0; i < N; ++i) {
presum.push_back(presum[i] + a[i]);
}
if (presum[N] < S) {
cout << 0 << endl;
return;
}
int ans = N;
for (int i = 0; presum[N] - presum[i] >= S; ++i) {
int len = distance(presum.begin() + i,
lower_bound(presum.begin() + i,
// here can ALSO be presum + N + 1
presum.end(), presum[i] + S));
ans = min(ans, len);
}
cout << ans << endl;
}
int main(void) {
#ifndef ONLINE_JUDGE
freopen("3061.txt", "r", stdin);
#endif
int n;
cin >> n;
while (n--) {
solve();
}
}
方法二:
C
#include <stdio.h>
int N, S;
int a[100 * 1000 + 10];
void solve() {
scanf("%d%d", &N, &S);
for (int i = 0; i < N; ++i) {
scanf("%d", a + i);
}
int i = 0, j = 0, sum = 0, ans = N + 1;
while (1) {
while (sum < S && j < N) {
sum += a[j];
++j;
}
if (sum < S) {
break;
}
ans = (ans < j - i) ? ans : j - i;
sum -= a[i];
++i;
}
if (ans == N + 1) {
ans = 0;
}
printf("%d\n", ans);
return;
}
int main(void) {
int n;
scanf("%d", &n);
while (n--) {
solve();
}
return 0;
}
Common Lisp
(defvar *N*)
(defvar *S*)
(defvar *a*)
(defvar n)
(defun print-array ()
(loop for i from 0 to (1- (length *a*)) do
(format t "~d " (elt *a* i)))
(format t "~%"))
(defun solve ()
(let ((sum 0)
(i 0)
(j 0)
(ans (+ 1 *N*)))
(block while
(loop
(do ()
((or (>= sum *S*)
(>= j *N*)))
(incf sum (aref *a* j))
(incf j))
(if (< sum *S*)
(return-from while))
(setf ans (min ans (- j i)))
(decf sum (aref *a* i))
(incf i)))
(if (equal ans (1+ n))
(setf ans 0))
(format t "~d~%" ans)))
(with-open-file (*standard-input*
"3061.txt"
:if-does-not-exist nil)
(setf n (read))
(dotimes (i n)
(setf *N* (read))
(setf *S* (read))
(setf *a* (make-array *N*
:element-type 'integer
:fill-pointer 0
:adjustable t))
(dotimes (j *N*)
(vector-push-extend (read) *a*))
(solve)))