Bỏ qua để đến nội dung

Dãy con tăng dài nhất (LIS)

Mức độ: Nâng cao

Từ dãy 3 1 4 1 5 9 2 6, xóa đi một số phần tử (giữ nguyên thứ tự các phần tử còn lại) để được dãy tăng ngặt dài nhất. Ví dụ 1 4 5 9 hoặc 3 4 5 6, dài 4. Đây là bài dãy con tăng dài nhất (LIS), bài mẫu quen thuộc nhất của quy hoạch động.

Gọi dai[i] là độ dài dãy con tăng dài nhất kết thúc tại ai. Dãy đó gồm ai đứng cuối, trước nó là một dãy con tăng kết thúc tại aj nào đó với j đứng trước i và aj nhỏ hơn ai (hoặc không có gì):

dai[i] = 1 + max(dai[j] với j nhỏ hơn i và aj nhỏ hơn ai) (max của tập rỗng coi là 0)

i12345678
ai31415926
dai[i]11213424

Đáp số là dai lớn nhất, 4. Mỗi i xét mọi j đứng trước, cả bài khoảng n2 / 2 bước: n = 5000 là khoảng 107, n = 105 thì quá chậm.

Giữ mảng duoi: duoi[k] là số cuối nhỏ nhất của một dãy con tăng dài k + 1 trong các phần tử đã xét. Đuôi càng nhỏ càng dễ nối thêm, nên chỉ cần nhớ đuôi nhỏ nhất cho mỗi độ dài.

Mảng duoi luôn tăng ngặt (dãy dài hơn thì đuôi lớn hơn). Khi xét ai:

  • tìm vị trí k đầu tiên có duoi[k] ≥ ai bằng tìm kiếm nhị phân;
  • nếu không có (ai lớn hơn mọi đuôi): nối ai vào cuối, độ dài tăng 1;
  • nếu có: thay duoi[k] = a[i] (có dãy dài k + 1 với đuôi nhỏ hơn trước).
aiduoi sau khi xét
33
11
41 4
11 4
51 4 5
91 4 5 9
21 2 5 9
61 2 5 6

Độ dài mảng duoi cuối cùng là đáp số, 4. Lưu ý mảng duoi không phải là một dãy con tăng (1 2 5 6 không xuất hiện theo đúng thứ tự trong dãy), chỉ độ dài của nó là đúng.

import sys
from bisect import bisect_left
du_lieu = sys.stdin.read().split()
n = int(du_lieu[0])
duoi = []
for x in map(int, du_lieu[1:1 + n]):
k = bisect_left(duoi, x) # vị trí đầu tiên có duoi[k] >= x
if k == len(duoi):
duoi.append(x)
else:
duoi[k] = x
print(len(duoi))

Mỗi phần tử một lần tìm kiếm nhị phân, cả bài khoảng n × log2n bước.

Đề hỏiThay đổi
dãy con không giảm dài nhấtdùng bisect_right (C++ upper_bound) thay bisect_left
dãy con giảm dài nhấtđổi dấu mọi số rồi tìm dãy con tăng
ít nhất phải xóa mấy số để dãy tăngn - (độ dài dãy con tăng dài nhất)
cặp (rộng, cao), xếp lồng nhausắp xếp theo rộng tăng dần, rộng bằng nhau thì cao giảm dần, rồi tìm dãy con tăng theo cao

Với cặp (rộng, cao), cao giảm dần khi rộng bằng nhau để hai hộp cùng rộng không bị chọn lồng vào nhau.

Gồm 16 bài, chia thành 4 nhóm từ dễ đến khó. Mỗi bài có một dữ liệu kiểm tra: các bạn chạy chương trình của mình với dữ liệu đó rồi so với đáp số.

Dòng đầu có n (1 ≤ n ≤ 2 × 105), dòng thứ hai có n số nguyên (|ai| ≤ 109). In ra độ dài dãy con tăng ngặt dài nhất.

Ví dụ:

NhậpIn ra
8
3 1 4 1 5 9 2 6
4

Kiểm tra: nhập

12
10 -3 7 7 2 8 -1 9 4 5 6 1
Xem đáp số

5

Hướng dẫn giải chi tiết: liên hệ tác giả.

Dòng đầu có n (1 ≤ n ≤ 2 × 105), dòng thứ hai có n số nguyên (|ai| ≤ 109). In ra độ dài dãy con không giảm dài nhất (cho phép hai số liền nhau bằng nhau).

Ví dụ:

NhậpIn ra
7
2 2 1 3 3 2 4
5

Kiểm tra: nhập

10
5 5 5 1 1 6 1 5 5 2
Xem đáp số

5

Hướng dẫn giải chi tiết: liên hệ tác giả.

Dòng đầu có n (1 ≤ n ≤ 2 × 105), dòng thứ hai có n số nguyên (|ai| ≤ 109). In ra độ dài dãy con giảm ngặt dài nhất.

Ví dụ:

NhậpIn ra
7
5 8 3 7 2 6 1
4

Kiểm tra: nhập

10
-1 4 4 3 9 0 -2 5 -3 -8
Xem đáp số

6

Hướng dẫn giải chi tiết: liên hệ tác giả.

Bài 4. Độ dài dãy con tăng kết thúc tại từng vị trí

Phần tiêu đề “Bài 4. Độ dài dãy con tăng kết thúc tại từng vị trí”

Dòng đầu có n (1 ≤ n ≤ 2 × 105), dòng thứ hai có n số nguyên (|ai| ≤ 109). Với mỗi i, in ra độ dài dãy con tăng ngặt dài nhất kết thúc tại ai.

Ví dụ:

NhậpIn ra
8
3 1 4 1 5 9 2 6
1 1 2 1 3 4 2 4

Kiểm tra: nhập

10
4 2 6 3 5 1 7 7 0 8
Xem đáp số

1 1 2 2 3 1 4 4 1 5

Hướng dẫn giải chi tiết: liên hệ tác giả.

Dòng đầu có n (1 ≤ n ≤ 2 × 105), dòng thứ hai có n số nguyên (|ai| ≤ 109). In ra số phần tử ít nhất cần xóa để các phần tử còn lại tạo thành dãy tăng ngặt.

Ví dụ:

NhậpIn ra
6
4 2 5 3 6 1
3

Kiểm tra: nhập

10
1 9 2 8 3 7 4 6 5 5
Xem đáp số

5

Hướng dẫn giải chi tiết: liên hệ tác giả.

Dòng đầu có n (1 ≤ n ≤ 2 × 105), dòng thứ hai có n số nguyên (|ai| ≤ 109). Mỗi lần được đổi một phần tử thành số nguyên bất kỳ. In ra số lần đổi ít nhất để dãy tăng ngặt.

Ví dụ:

NhậpIn ra
5
1 2 2 3 4
2

Kiểm tra: nhập

8
5 1 2 3 10 4 5 6
Xem đáp số

4

Hướng dẫn giải chi tiết: liên hệ tác giả.

Hai bờ sông song song. Có n cặp thành phố muốn nối cầu, cặp thứ i nối điểm ai ở bờ trái với điểm bi ở bờ phải (các ai khác nhau, các bi khác nhau). Hai cây cầu cắt nhau nếu ai nhỏ hơn aj nhưng bi lớn hơn bj. Dòng đầu có n (1 ≤ n ≤ 2 × 105), n dòng sau mỗi dòng có a, b (1 ≤ a, b ≤ 109). In ra số cầu nhiều nhất xây được mà không có hai cầu nào cắt nhau.

Ví dụ:

NhậpIn ra
5
1 3
2 1
3 4
4 2
5 5
3

Kiểm tra: nhập

8
8 1
3 6
1 2
5 4
2 7
7 8
4 3
6 5
Xem đáp số

5

Hướng dẫn giải chi tiết: liên hệ tác giả.

Có n hộp, hộp thứ i có đáy hình chữ nhật rộng wi, dài hi (không được xoay). Hộp A bỏ vừa vào hộp B nếu wA nhỏ hơn wB và hA nhỏ hơn hB. Dòng đầu có n (1 ≤ n ≤ 2 × 105), n dòng sau mỗi dòng có w, h (1 ≤ w, h ≤ 109). In ra số hộp nhiều nhất lồng được vào nhau thành một chồng.

Ví dụ:

NhậpIn ra
4
5 4
6 4
6 7
2 3
3

Kiểm tra: nhập

8
3 3
3 5
4 4
4 6
5 5
2 8
6 7
1 1
Xem đáp số

5

Hướng dẫn giải chi tiết: liên hệ tác giả.

Có n tấm thẻ đến lần lượt, tấm thứ i ghi số ai. Mỗi tấm được đặt lên trên cùng một cột: tấm mới phải ghi số nhỏ hơn hoặc bằng tấm đang trên cùng cột đó, hoặc lập một cột mới. Dòng đầu có n (1 ≤ n ≤ 2 × 105), dòng thứ hai có n số ai (|ai| ≤ 109). In ra số cột ít nhất.

Ví dụ:

NhậpIn ra
7
5 2 6 1 3 4 2
3

Kiểm tra: nhập

10
3 3 3 1 4 1 5 9 2 6
Xem đáp số

4

Hướng dẫn giải chi tiết: liên hệ tác giả.

Dòng đầu có n (1 ≤ n ≤ 2 × 105), dòng thứ hai có n số nguyên (|ai| ≤ 109). Dãy con hình núi là dãy con tăng ngặt rồi giảm ngặt (phần tăng hoặc phần giảm có thể chỉ gồm một số là đỉnh). In ra độ dài dãy con hình núi dài nhất.

Ví dụ:

NhậpIn ra
8
1 11 2 10 4 5 2 1
6

Kiểm tra: nhập

10
3 1 4 1 5 9 2 6 5 3
Xem đáp số

7

Hướng dẫn giải chi tiết: liên hệ tác giả.

Bài 11. Dãy con tăng với bước nhảy không quá k

Phần tiêu đề “Bài 11. Dãy con tăng với bước nhảy không quá k”

Dòng đầu có n, k (1 ≤ n ≤ 3000, 1 ≤ k ≤ 109), dòng thứ hai có n số nguyên (|ai| ≤ 109). Tìm dãy con tăng ngặt dài nhất mà hai số liền nhau trong dãy con chênh nhau không quá k. In ra độ dài của nó.

Ví dụ:

NhậpIn ra
7 2
1 5 2 3 6 4 8
4

Kiểm tra: nhập

10 3
10 1 4 2 7 5 8 11 9 12
Xem đáp số

6

Hướng dẫn giải chi tiết: liên hệ tác giả.

Dòng đầu có n, m (1 ≤ n, m ≤ 3000), dòng thứ hai có n số của dãy A, dòng thứ ba có m số của dãy B (|giá trị| ≤ 109). In ra độ dài dãy dài nhất vừa là dãy con của A, vừa là dãy con của B, và tăng ngặt.

Ví dụ:

NhậpIn ra
5 5
2 3 1 6 5
3 1 2 6 5
2

Kiểm tra: nhập

8 7
1 4 2 5 3 6 7 2
4 1 5 2 6 3 7
Xem đáp số

4

Hướng dẫn giải chi tiết: liên hệ tác giả.

Dòng đầu có n (1 ≤ n ≤ 2 × 105), dòng thứ hai có n số nguyên (|ai| ≤ 109). In ra độ dài dãy con tăng ngặt dài nhất trên dòng đầu, dòng thứ hai in ra các vị trí (đánh số từ 1) của một dãy như vậy. Nếu có nhiều dãy, in dãy có vị trí cuối cùng lớn nhất; nếu vẫn còn nhiều, chọn dãy có vị trí áp chót lớn nhất, và cứ thế đi ngược về đầu.

Ví dụ:

NhậpIn ra
8
3 1 4 1 5 9 2 6
4
2 3 5 8

Kiểm tra: nhập

10
2 7 1 8 2 8 1 8 2 8
Xem đáp số
3
7 9 10

Hướng dẫn giải chi tiết: liên hệ tác giả.

Dòng đầu có n (1 ≤ n ≤ 3000), dòng thứ hai có n số nguyên (|ai| ≤ 109). In ra số dãy con tăng ngặt có độ dài lớn nhất (hai dãy con khác nhau nếu tập vị trí khác nhau), chia lấy dư 109 + 7.

Ví dụ:

NhậpIn ra
6
1 3 2 4 3 5
3

Kiểm tra: nhập

10
2 2 2 2 2 2 2 2 2 2
Xem đáp số

10

Hướng dẫn giải chi tiết: liên hệ tác giả.

Dòng đầu có n (1 ≤ n ≤ 2 × 105), dòng thứ hai có n số nguyên dương (ai ≤ 109). In ra tổng lớn nhất của một dãy con tăng ngặt (không cần dài nhất).

Ví dụ:

NhậpIn ra
6
1 101 2 3 100 4
106

Kiểm tra: nhập

10
5 3 8 1 9 2 10 4 7 6
Xem đáp số

32

Hướng dẫn giải chi tiết: liên hệ tác giả.

Dòng đầu có n (1 ≤ n ≤ 2 × 105), dòng thứ hai có n số nguyên (|ai| ≤ 109). Dãy con lên xuống là dãy con mà các hiệu giữa hai số liền nhau đổi dấu luân phiên (dương, âm, dương… hoặc âm, dương, âm…; không có hiệu bằng 0). Dãy một số cũng là dãy lên xuống. In ra độ dài dãy con lên xuống dài nhất.

Ví dụ:

NhậpIn ra
6
1 7 4 9 2 5
6

Kiểm tra: nhập

10
1 17 5 10 13 15 10 5 16 8
Xem đáp số

7

Hướng dẫn giải chi tiết: liên hệ tác giả.