Dãy con dài nhất có tổng lớn hơn bằng p
2017-08-02Bài gốc
Đề bài
Cho dãy số nguyên a1, a2, …, an.
Dãy số ai, ai+1, …, aj với 1 ≤ i ≤ j ≤ n được gọi là dãy con của dãy số đã cho và khi đó, j-i+1 được gọi là độ dài, còn ai+ai+1…+aj được gọi là trọng lượng của dãy con này.
Yêu cầu: cho số nguyên p, trong số các dãy con của dãy số đã cho có trọng lượng không nhỏ hơn p hãy tìm dãy con có độ dài lớn nhất.
Giới hạn:
- 1 ≤ n ≤ 50000
- -20000 ≤ ai ≤ 20000
- -109 ≤ p ≤ 109
Định dạng test
Input:
- Dòng đầu tiên ghi hai số nguyên n và p cách nhau bởi dấu cách.
- Dòng thứ i trong số n dòng tiếp theo chứa số nguyên ai là số hạng thứ i của dãy số đã cho, i = 1, 2, …, n.
Output:
- Ghi ra số nguyên k là độ dài của dãy con tìm được (qui ước: nếu không có dãy con nào thỏa mãn điều kiện đặt ra thì k = -1.
Ví dụ:
Thuật toán
Chưa chứng minh được tính đúng đắn của thuật toán dưới đây.
Source code
Ngôn ngữ: C++.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
const int N = 5e4 + 5;
int n, a[N], p, f[N];
bool prefixMin[N];
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
// input & init
cin >> n >> p;
prefixMin[0] = true;
f[0] = 0;
int min = 0;
FOR(i,1,n) {
cin >> a[i];
// prefix sum
f[i] = f[i-1] + a[i];
// prefix min
if (f[i] < min) {
prefixMin[i] = true;
min = f[i];
}
}
// greedy
int res = -1;
int pos = n;
for(int i = n; i >= 0; i--)
if (prefixMin[i])
while(i < pos) {
if (f[pos] - f[i] >= p) {
res = max(res, pos - i);
break;
}
pos--;
}
// output
cout << res;
return 0;
}
Độ phức tạp
O(N)