1. Trang chủ
  2. » Luận Văn - Báo Cáo

(Sáng kiến kinh nghiệm) chuyên đề môn tin học học binary indexed trees từ các kĩ thuật đơn giản nhất

22 3 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 22
Dung lượng 305,5 KB

Nội dung

Học Binary Indexed Trees từ kĩ thuật đơn giản Nguyễn Như Thắng- GV THPT Chuyên Lào Cai Mở đầu: Bài toán sở: Cho dãy số nguyên a1 , a2 , an , có m câu hỏi, câu hỏi yêu cầu tính tổng đoạn liên tiếp từ li đến ri với i = m Với cách giải thông thường yêu cầu ta duyệt từ li đến ri để tính tổng, độ phức tạp thuật toán O(m.n) Nếu m n cỡ 105 chắn thực thời gian cho phép Để giải vấn đề, ta cải tiến cách tính trước tổng cộng dồn s[i] tổng số từ a1 → đọc liệu vào thời gian chung O(n) Sau đó, câu hỏi ta thực thời gian O(1) cách lấy s [ ri ] − s [ li − 1] , độ phức tạp tốn cịn O(m+n) Tuy nhiên ta mở rộng toán cách bổ sung thêm m yêu cầu đan xen vào m yêu cầu ban đầu là: cập nhật lại trị = val Khi đó, việc tính sẵn tổng cộng dồn s[i] lại trở nên vơ nghĩa Vì dãy số liên tục biến động, s[i] biến động, độ phức tạp tốn quay nguyên trạng ban đầu O(m.n) Tuy nhiên, ý tưởng việc cộng dồn lại không vô nghĩa ta kết hợp với số nhị phân để tạo giá trị cộng dồn quản lý số nhị phân (Binary Index Tree) Mỗi cần cập nhật, tính tổng đoạn, ta hồn tồn thực thời gian chung O(logN) Độ phức tạp toán O(NlogN+2MlogN) Cấu trúc liệu BIT có chất ý tưởng cộng dồn mã hóa đoạn cộng dồn quản lý số nhị phân Đây loại cấu trúc liệu để thuật toán thực nhanh Trong viết thảo luận cấu trúc liệu Binary Indexed Trees (cây nhị phân số) Theo Peter M Fenwick cấu trúc lần sử dụng để nén liệu Bây thường sử dụng để lưu trữ tần số thao tác với bảng tần số tích lũy u cầu tốn sở thay việc tìm min, max, 1 Giới thiệu toán Xét toán sau Chúng ta có n hộp truy vấn là: Thêm số viên bi vào hộp i Tính số lượng viên bi từ hộp k tới hộp l Giải pháp đơn giản có độ phức tạp thời gian O(1) cho truy vấn O(n) cho truy vấn Giả sử thực m truy vấn Trường hợp xấu (khi tất truy vấn 2) có độ phức tạp thời gian O(n×m) Sử dụng cấu trúc segment tree, giải tốn với trường hợp xấu có độ phức tạp thời gian O(m.log2n) Một cách khác sử dụng cấu trúc Binary Indexed Trees, với phức tạp thời gian trường hợp xấu O(m.log2n), Binary Indexed Trees dễ viết mã yêu cầu khơng gian nhớ so với segment tree Tương ứng O(n) so với O(4n) Để hiểu BIT, bạn cần hiểu kĩ phần Mở đầu (nói cộng dồn), biết cách biểu diễn số nhị phân, phép toán logic bit Ký hiệu • • • • • BIT - Binary Indexed Tree MaxVal - giá trị lớn tần số khác không f[i] - tần số (số lần xuất hiện) giá trị với số i, i = … MaxVal c[i] - tần số tích lũy cho số i (c[i] = f[1] + f[2] + + f[i]) tree[i] - tổng tần số f lưu trữ BIT với số i (phần sau mô tả số có nghĩa gì) Đơi viết tần số thay tổng tần số lưu trữ • BIT num - số bù số nguyên num (đảo ngược chữ số nhị phân num: → 1, → 0) Chú ý: Thông thường đặt f[0] = 0, c[0] = 0, tree[0] = 0, đơi ta bỏ qua số Ý tưởng tảng Mỗi số nguyên biểu diễn tổng lũy thừa 2, hay biểu diễn hệ số Theo cách này, tần số tích lũy biểu diễn tổng tập tần số Trong toán này, tập chứa số liên tiếp tần số idx số BIT r vị trí chữ số cuối (chữ số bên phải nhất) biểu diễn nhị phân idx tree[idx] tổng tần số f từ số (idx - 2r + 1) tới số idx (xem bảng để hiểu rõ hơn) Chúng ta nói idx quản lí số từ (idx - 2r + 1) tới idx (chú ý việc quản lí chìa khóa thuật toán cách thao tác với cây) Ví dụ: Theo số nhị phân: 12(10)=1100(2), nút 12 quản lý nút có số từ (=12-22+1) đến 12 Bảng cộng dồn tần số (tree) tổng giá trị nút quản lý: ví dụ: tree[12]=f[9]+f[10]+f[11]+f[12]; tree[14]=f[13]+f[14]; tree[1]=f[1]; tree[2]=f[1]+f[2]; tree[4]=f[1]+ f[2]+f[3]+f[4]; tree[5]=f[5]; tree[6]=f[5]+f[6];… Hãy quan sát bảng giá trị minh họa bên dưới: idx f[idx] c[idx] tree[idx] 1 1 1 3 idx Các số mà idx quản lí idx Các số mà idx quản lí 4 5 1 9 2 10 10 8 12 12 Bảng 14 3 11 11 10 19 11 21 4 12 12 5 13 13 12 23 11 13 26 6 14 13 14 14 27 7 15 15 Bảng - Bảng quản lí số Hình Cây quản lí số (cột hiển thị đoạn tần số tích lũy phần tử đầu) Hình Cây tần số (tree) 15 27 16 29 29 8 16 16 Giả sử tìm tần số tích lũy 13 phần tử sau: Trong biểu diễn nhị phân, 13 1101 Vì vậy, tính c[1101] = tree[1101] + tree[1100] + tree[1000] = + 11 + 12 = 26 Tổng đoạn từ đến 13 c[13]=tree[13]+tree[12]+tree[8] Tính tổng từ đoạn có số 12 đến 13 sau: c[13]-c[11]=tree[13]+tree[12]+tree[8]-(tree[11]+tree[10]+tree[8])=tree[13]+ tree[12]-tree[11]-tree[10]=3+11-2-7=5 f[12]+f[13]=2+3 Lấy chữ số bên phải Chữ số bên phải hay gọi chữ số cuối Để lấy số cuối đó, ta gọi num số nguyên ta cần lấy số cuối Giả sử num có dạng nhị phân a1b, a biểu diễn chữ số nhị phân trước số cuối b gồm chữ số không đằng sau số cuối (b=000 000nghịch đảo b (~b) = b =111…111) Số bù số num ~num, ~num xác định cách nghịch đảo toàn bit biểu diễn num Số bù cách biểu diễn số đối số num Được xác định cách lấy số bù cộng thêm Vậy ta có: (num)= a 1b (~num)= a b  (-num)= a b (num)+(-num)=00…00 Phép toán AND (num)&(-num)= ( a 1b )&( a b ) = 010 0= 2r (ở r vị trí số cuối cùng) Vậy ta dễ dàng lập số cuối phép toán (num&-num) C++ a1b & a1b -= 010 Tính tần số tích lũy Nếu muốn đọc tần số tích lũy số nguyên idx, cộng tree[idx] vào sum, sau loại bỏ bit cuối idx từ (tức thay đổi chữ số cuối không) lặp lại điều idx lớn Chúng ta sử dụng hàm sau (viết C++): int read(int idx) { Vòng lặp int sum = 0; Vòng lặp while (idx > 0) { sum += tree[idx]; idx -= (idx & -idx); Vịng lặp } return sum; } Ví dụ với idx = 13, sum = 0: Vòng Vị trí số idx lặp 13 = 1101 12 = 1100 = 1000 0=0 idx & Tree[idx] cuối - 11 12 - Sum -idx (20) (22) (23) - 14 26 - Vì vậy, kết tần số tích lũy số 13 26 Số lần lặp hàm số bit idx, số lần lặp nhiều log2MaxVal Độ phức tạp thời gian hàm read: O(log2MaxVal) Hình – Mũi tên minh họa đường từ số 13 tới việc tính sum Cập nhật lại giá trị nút Để cập nhật giá trị nút f[idx] tác động lên tất nút quản lý nút tree[idx] Ví dụ: để cập nhật lại giá trị nút idx=9; ta cần cập nhật nút 10, 12,16,32,64,…2k ( kMaxVal Biểu diễn nút số nhị phân theo cập nhật nút theo thứ tự sau: Bắt đầu từ nút idx=9=100121010211002100002100000210000002… Hàm trong C++ cài đặt sau: Vòng lặp void update(int idx, int val) { while (idx

Ngày đăng: 15/06/2021, 14:27

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w