Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 9

Bàn luận về 0-1 trong

10 tin học
Trần Ngọc Long-Nguyễn Đình Phúc
THÀ NH VIÊN DỰ TUYỂN 2018
“Tôi học để xây cuộc đời tôi !!!”
-Trần Ngọc Long -

Thư viện Hoàng Gia Gouta nổi tiếng ở Turingen, Đức (Schlossbiliothke zu
Gotha) có lưu giữ một bản thảo quý có tiêu đề : “0, 1 và mọi thứ”. Hãy thừa nhận vẻ
đẹp, sự tuyệt vời của nó và khám phá nó như cội nguồn của cuộc sống.

Chương 1 : Ứng dụng nhị phân trong cấu trúc dữ liệu.


 Ma trận:
Ví dụ 1: Cho một ma trận m*n. Ô (i, j) chứa một số khác 0 và 1. Giá trị ban đầu của
mỗi ô là 0. Tại mỗi lần, chọn đỉnh trái trên có tọa độ (x, y) và đỉnh phải dưới (a, b),
đảo ngược lại tất cả các số trong hình chữ nhật. Nói cách khác đổi 1 thành 0 và 0
thành 1. Trả lời các truy vấn giá trị của ô (i, j).
Nhận xét: Ta để ý tới trạng thái chỉ có “lật” và không “lật”, nên ta chuyển trạng thái
thành 0(không “lật”) và 1(“lật”). Vậy việc công việc trở về lưu lại số lần “lật” để xác
định giá trị của ô.
 Bài toán thứ 1: Bây giờ ta giải quyết bài toán với mảng một chiều d độ dài n,
với mỗi lần cập nhật ta đánh dấu 2 vị trí l và r+1 trong hàng là vị trí bắt đầu
“lật” và kết thúc “lật” và thêm 1 vào 2 nút này.

[1]
x

Sau đó với mỗi truy vấn, bạn tính tổng prefix của hàng: Sumx =∑di . Nếu Sumx
mod 2 = 1 thì ô đó là 1, ngược lại là 0.


Như vậy bài toán con được giải quyết đẹp đẽ với trợ giúp của cây IT. Độ phức tạp của
1 query là O(logN).
 Bài toán thứ 2: Kích thước. Câu hỏi đặt ra là với mảng 2D liệu hương pháp
trên còn đúng hay không ? Nếu ta đánh dấu hình chữ nhật được cập nhật bằng
cách cộng vào mỗi điểm (x1, y1), (x2+1, y1), (x1, y2+1), (x2+1, y2+1) thêm
1 đơn vị.

[2]
i =x , j =y
Như vậy kiểm tra màu tại một điểm (x, y) bằng cách lấy tổng các ô trong hình
chữ nhật A có đỉnh trái trên – phải dưới là (1, 1) và (x, y).

[3]
Vậy tại sao nó đúng ? Ta xét 1 điểm nằm trong hình chữ nhật được update, chắc
chắn hình chữ nhật A chứa 1 điểm (x1, y1). Khi ra ngoài hình chữ nhật mà không
vượt qua điểm (x2, y2), số điểm nằm trong A có thêm (x2+1, y1) hoặc (x1, y2+1).
Cuối cùng khi vượt qua điểm (x2, y2), trong A có tất cả 4 điểm. Mặt khác các
update độc lập với nhau nên ta không bận tâm đến các hình chữ nhật lồng nhau.
Như vậy ta có đ.p.c.m.
 Bài toán thứ 3: Liệu cách làm trên còn đúng cho một ma trận N chiều hay
không ? Hiển nhiên câu trả lời là được. Nếu ta cập nhật cho 2𝑛 điểm trên mỗi
chiều và tính 𝑆𝑢𝑚(𝑥1, 𝑥2. . . , 𝑥𝑛) thì ta vẫn thu được kết quả bài toán.
 Bài toán thứ 4: Vấn đề nảy sinh khi dùng IT để quản lí từng chiều của truy vấn
update. Việc mở rộng IT cho N chiều không đơn giản và xác suất xảy ra lỗi rất
cao. Khi đó, ta quay lại một cấu trúc dữ liệu đơn giản và thuận tiện và hiệu quả
hơn. Đó là cây BIT !!! Đây là một ý tưởng cổ điển của ứng dụng nhị phân.
Chỉ số của mỗi phần tử được mã hóa thành một chuỗi nhị phân: 11 = 10112 .
Sau đó ta xác thông tin dựa vào biểu diễn của mã nhị phân này. Nếu số nút là
x, thì nút lưu giữ giá trị trong khoảng 2𝑘 giá trị với k là vị trí đầu tiên của bit 1
trong biểu diễn nhị phân của x.

Các thao tác xây dựng và xử lí trên BIT được thực hiện trên tóm gọn trong 2 thao tác:
Update và Get. Code mẫu: https://ideone.com/jVjmsL. Với mọi thao tác độ phức tạp
luôn là O(logN). Tạm gác lại vấn đề này ở đây. Ta sẽ quay lại với nó ở phần luyện tập
cuối bài viết.

Tóm tắt:

[4]
Việc suy nghĩ đến tư tưởng nhị phân để xây dựng một cây BIT mấu chốt nằm ở việc
liên kết số thập phân với số nhị phân, nhằm lưu giữ thông tin và đơn giản hóa một cách
khéo léo cách vấn đề trong cuộc sống. Bên cạnh đó, việc khai thác và sử dụng cây BIT
hoàn toàn tiết kiệm, hiệu quả, dễ bảo trì và phát triển. Đây được đánh giá là một data
structure phù hợp với các xử lí không quá phức tạp và giới hạn bộ bé.

Chương 2 : Suy nghĩ nhị phân - việc giải quyết vấn đề.
 Sudoku:
Ví dụ 2: Sudoku là một bảng gồm 9 ô vuông đơn vị (được in viền đậm). Mỗi ô vuông
đơn vị lại được chia làm 9 ô nhỏ hơn. Như vậy, có thể coi bảng trên là một hình
vuông 9*9. Một bảng được định nghĩa là đúng nếu thỏa mãn:
1. Trên mỗi hàng và cột có đúng 9 số phân biệt.
2. Trong mỗi hình đơn vị có đúng 9 số phân biệt.
Ta bắt đầu với các bài toán:
 Bài toán thứ 1: Lấp đầy bảng với một số số đã biết. Đây là một vấn đề cổ điển
với cách suy nghĩ đơn giản nhất: Ta xét tất cả khả năng và so sánh với các số
cho trước trong bảng ban đầu. Nếu thỏa mãn các vị trí cho trước, ta thu được
một cách xếp đúng. Nghe có vẻ đơn giản nhưng thực tế: Người ta tính toán
được có tất cả : 6.670.903.752.021.072.936.960 ~ 6.67 ∗ 1021 khả năng để
một bảng là đúng. Đây là một con số không tưởng trong thực tế. Như vậy ta
đòi hỏi một cách thức tối ưu hơn.

 Bài toán thứ 2: Ta cần những bước cắt tỉa hiệu quả nhất để cải thiện tốc độ bài
toán. Ta tiến hành các bước: Ghi lại các ô trống trong mỗi hình vuông đơn vị
vào bảng. Điền các số với khả năng duy nhất và sắp xếp các số còn lại theo số
lượng có thể. Thay lần lượt các số có thể vào các ô còn lại. Tuy nhiên sau mỗi
cách chọn, khả năng của các ô còn lại cũng thay đổi. Ta cần sort lại và tiếp tục
điền. Kết quả thu được là : “TLE”.

 Bài toán thứ 3: Tối ưu bằng ứng dụng nhị phân sẽ giúp bài toán này. Nén trạng
thái và tượng tượng một hình vuông con là một số nhị phân 9 bit, tạo thành từ
bit 1, … bit 9. Như vậy mỗi đại diện bởi một số nguyên không quá 511. Như
vậy bằng mỗi tìm kiếm, bạn liệt kê một số nguyên thông qua các thao tác bit.
Tính toán xem hàng, cột và các khối 3*3 có thể đạt được không ? Ta thực hiện
các bước thử với các ô có số khả năng ít hơn trước để tối ưu. Đây là một cách
giải hoàn toàn phù hợp với yêu cầu.

 Yêu cầu:
[5]
Ví dụ 3 : Cho N điểm trong không gian năm chiều A(x1, x2, x3, x4, x5). Tìm 2 điểm
thỏa mãn khoảng cách Manhattan của chúng là lớn nhất. Nói cách khác, tìm X(x1,
x2, x3, x4, x5) và Y(y1, y2, y3, y4, y5) sao cho (|𝑥1 − 𝑦1| + |𝑥2 − 𝑦2| +
|𝑥3 − 𝑦3| + |𝑥4 − 𝑦4| + |𝑥5 − 𝑦5|) max.
Phân tích:
 Bài toán thứ 1: Tất nhiên ta được đến giải thuật O(𝑁 2 ) bằng cách for hết tất cả
các cặp X, Y trong N số. Tuy nhiên giải thuật này không thể qua với giới hạn
N <= 1e5. Như vậy tôi có thể làm gì ? Ta thấy một điều đặc biệt là số chiều ít
hơn rất nhiều so với số điểm. Lợi dụng nó được không ? Ta hãy thử xét một
vài bài toán con như sau:
1. Nếu N điểm thuộc không gian 1 chiều: Ta sẽ quét từ trái sang phải
và ghi lại giá trị max và min của chúng. Như vậy ta dễ dàng thu được
đáp án. Tuy nhiên mối liên hệ với bài toán ban đầu vẫn chưa xuất
hiện. Xét tiếp bài toán con thứ 2.

2. Nếu N điểm thuộc không gian 2 chiều: A(Xi, Yi) và B(Xj, Yj). Như
vậy khoảng cách Manhattan giữa A và B là: 𝑓(𝐴, 𝐵) = |𝑋𝑖 − 𝑋𝑗| +
|𝑌𝑖 − 𝑌𝑗|. Tuy nhiên ta dễ thấy 𝑓(𝐴, 𝐵) = max(±(𝑋𝑖 − 𝑋𝑗) ±
(𝑌𝑖 − 𝑌𝑗)) = |𝑋𝑖 − 𝑋𝑗| + |𝑌𝑖 − 𝑌𝑗|.

Khai triển 𝑓(𝐴, 𝐵) = max(±(𝑋𝑖 − 𝑋𝑗) ± (𝑌𝑖 − 𝑌𝑗)) ta có:


𝑓(𝐴, 𝐵) = max(𝑓(𝐴, 𝐵), + 𝑋𝑖 − 𝑋𝑗 + 𝑌𝑖 − 𝑌𝑗)
𝑓(𝐴, 𝐵) = max(𝑓(𝐴, 𝐵), − 𝑋𝑖 + 𝑋𝑗 + 𝑌𝑖 − 𝑌𝑗)
𝑓(𝐴, 𝐵) = max(𝑓(𝐴, 𝐵), − 𝑋𝑖 + 𝑋𝑗 − 𝑌𝑖 + 𝑌𝑗)
𝑓(𝐴, 𝐵) = max(𝑓(𝐴, 𝐵), + 𝑋𝑖 − 𝑋𝑗 − 𝑌𝑖 + 𝑌𝑗)
Không khó để nhận ra Xi và Xj luôn trái dấu, Yi và Yj cũng vậy. Như
vậy bứt phá thêm 1 bước nữa: Ta xét tất cả dấu của bộ (Xi, Yi) sẽ có
tất cả 4 trường hợp (+𝑋𝑖 + 𝑌𝑖), (−𝑋𝑖 + 𝑌𝑖), ( 𝑋𝑖 − 𝑌𝑖), ( −𝑋𝑖 − 𝑌𝑖)
tương ứng với các tập (+ +), (+ −), (− +), (−−). Bây giờ với mỗi
điểm, ta cũng không cần thiết quan tâm đến X và Y nữa vì ta đã xét
hết tất cả các trường hợp rồi. Với mỗi giá trị max của một bộ dấu, ta
trừ đi min của bộ đó. Như vậy tất nhiên đảm bảo hai giá trị là ngược
dấu. Vậy là ta vừa tìm được mối liên kết tuyệt vời ẩn sau manh mối
“Không gian năm chiều”. “Có lẽ khai thác một điều kiện đặc biệt
hoặc một góc nhìn khác chính là mấu chốt của mọi solutions”. Vậy
nếu điểm thuộc không gian 2 chiều mà đúng thì ba chiều, bốn chiều
và năm chiều có còn đúng hay không ? Ta xét tiếp bài toán con thứ
3.

[6]
3. Nếu N điểm trên nằm trên mặt phẳng 3 chiều. Khoảng cách
Manhattan cho 2 điểm A(Xi, Yi, Zi) và B(Xj, Yj, Zj) lúc này:
𝑓(𝐴, 𝐵) = |𝑋𝑖 − 𝑋𝑗| + |𝑌𝑖 − 𝑌𝑗| + |𝑍𝑖 − 𝑍𝑗|
= max(±(𝑋𝑖 − 𝑋𝑗) ± (𝑌𝑖 − 𝑌𝑗) ± (𝑍𝑖 − 𝑍𝑗))
Tương tự như bài toán con thứ 2, ta luôn có : Xi-Xj, Yi-Yj, Zi-Zj là
ngược dấu, hay ta có tất cả 2𝑠ố 𝑐ℎ𝑖ề𝑢 bộ dấu: (+ + +), (+ +
−), … , (− − −). Làm tương tự, ta cũng có thể thu được kết quả như
mong muốn. Như vậy bước nhảy từ N chiều lên (N+1) chiều là hoàn
toàn thỏa mãn. Bây giờ, hãy bước tiếp trước khi quay lại với bài toán
ở cuối phần luyện tập.
Ví dụ 4: Cho bò ăn là một việc làm hằng ngày của nông dân John, nhưng mỗi lần
cho bò ăn lại là một bất ngờ đi kèm thách thức. N con bò của anh, (1 <= N <= 1e5)
được đánh số từ 1 đến N, đang tiến đến cuộc cải cách phân chia giai cấp. Bò #1 là
ở tầng lớp cao nhất, sau đó đến #2, #3, … #N là thấp nhất. Mỗi con bò được tặng
một số trong khoảng 0 → 221 − 1. Anh chỉ có thể cho các con bò trong đoạn (l, r)
ăn sao cho tổng xor của các số mà chúng được tặng là max. Nói cách khác, nếu gọi
Ai là số mà con bò thứ i nắm giữ, hãy tìm 1 đoạn (l, r) thoả mãn: Al xor A(l+1) xor
… xor Ar = max.
Chú ý: John luôn chọn con bò thuộc giai cấp cao nhất vào cuối. Nếu có nhiều đoạn
(l, r) thỏa mãn, hãy chọn cái ngắn nhất.
Phân tích: Bài toán đơn giản là cho một mảng Ai, tìm đoạn (l, r) có tổng xor là max.
Vậy ta sẽ thử tìm kiếm lời giải qua các bài toán.
 Bài toán thứ 1: Ta dễ thấy nếu for tất cả các đoạn (l, r) ta chắc chắn thu được
đáp án. Tuy nhiên, độ phức tạp lên đến O(𝑁 2 ) và với N <= 1e5 thì TLE là rõ.
Vậy ta sẽ làm gì trong hoàn cảnh này ?

 Bài toán thứ 2: Ta nhận thấy bài toán yêu cầu tìm một đoạn (l, r) có tổng xor
lớn nhất. Như vậy hướng đi của ta sẽ tập trung vào trạng thái nhị phân của các
Ai:
1. Xét về bộ nhớ: Một số Ai nằm trong khoảng 0 → 221 − 1. Như vậy
mỗi biểu diễn nhị phân của Ai sẽ có không quá 22 chữ số.

2. Xét về tính toán: Ta sẽ tối ưu việc tính xor đoạn (l, r) bằng việc tính
tổng xor dồn như sau: 𝑓[𝑖] là tổng xor của dãy tiền tố kết thúc tại i.
Như vậy theo tính chất đặc trưng của xor, tổng xor của đoạn (l, r) sẽ
= 𝑓(𝑟) 𝑥𝑜𝑟 𝑓(𝑙 − 1).

Vậy ta đã biết:

[7]
a. Mỗi Ai có không quá 22 bit, mỗi bit là 0 hoặc 1.

b. Với mỗi 𝑓(𝑖) cần tìm 𝑓(𝑗) thỏa mãn: 𝐴 = 𝑓(𝑖) 𝑥𝑜𝑟 𝑓(𝑗) =
𝑚𝑎𝑥.

c. Dễ thấy: Việc bật một bit ở vị trí i (từ trái sang) trong A và
tắt tất cả các bit 𝑖 + 1 → 𝑛 (độ dài biểu diễn nhị phân của A)
luôn tối ưu hơn tắt bit i và bật tất cả các bit còn lại.

Như vậy, một cây Trie là giải pháp không tệ cho bài toán này. Với mỗi node
cha có 2 con, biểu diễn cho 0(bên trái) và 1(bên phải). Node gốc không chứa
giá trị. Tầng thứ i tương đương với bit thứ i (từ trái sang). Như vậy việc lần
từng bit trên cây Trie luôn cho ta giá trị 𝑓(𝑗) thỏa mãn 𝐴 = 𝑓(𝑖) 𝑥𝑜𝑟 𝑓(𝑗) =
𝑚𝑎𝑥.
Tuy nhiên để luôn tìm được một vị trí 𝑗 có giá trị 𝑓(𝑗) là một tổng xor của một
đoạn tiền tố, ta lưu tại mỗi node u thuộc tầng i số giá trị 𝑓(𝑗) có i bit đầu thỏa
mãn path từ gốc đến node u. Như vậy ta cứ chạy zìn zin trên cây với mỗi 𝑓(𝑗)
tìm trong O(logN). Như vậy độ phức tạp là O(NlogN).
Một cách giải hoàn hảo !!!

Tóm tắt:
Qua một vài ví dụ, ta có thể phần nào hình dung ra một số những ứng dụng linh hoạt
và khéo léo của tư duy nhị phân. Vận dụng tư duy nhị phân trong tin học một cách
hợp lí không những làm sáng rõ mối liên hệ giữa các dữ liệu mà còn giúp khơi mở
những đột phá, sáng kiến để giải quyết vấn đề. Luyện tập các bài tập về bit cũng là
một cách rèn luyện khả năng vận dụng, suy nghĩ và sáng tạo. “...Hãy thừa nhận vẻ
đẹp, sự tuyệt vời của nó và khám phá nó như cội nguồn của cuộc sống...”.

Chương 3: Luyện tập.


1. Bốn bài trên tìm kiếm theo manh mối sau:
i. Bài 1: POJ Monthly,Lou Tiancheng.
ii. Bài 2: Stanford Local 2006.
iii. Bài 3: MIT Programming Contest, 2005.02.26.
iv. Adrian Vladu – 2005.
2. Tự tìm !!!
3. Tài liệu tham khảo :
i. 《算法艺术与信息学竞赛》 ,刘汝佳、黄亮著,清华
大学出版社, 2004 年 1 月第一版 <Cuộc thi về nghệ thuật

[8]
và tin học thuật toán, Liu Yijia, Huang Liang, Tsinghua
University Publishing ~ Xã hội, ấn bản đầu tiên, tháng 1 năm
2004>
ii. Peking University Judge Online: http://acm.pku.edu.cn/
iii. ZheJiang University Judge Online http://acm.zju.edu.cn/
iv. USA Computing Olympiad http://ace.delos.com/

Kết bài: (2h27’ sáng ngày 8/19/2019)


Mục tiêu đúng mới có hành động đúng. Đừng sợ khó sợ khổ, chỉ sợ mình không dám
quyết tâm theo đuổi đến cùng. Cố gắng lên !!! Tôi tin bạn làm được !!!

[9]

You might also like