Binary Indexed Tree (BIT)

4 212 1
Binary Indexed Tree (BIT)

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

Thông tin tài liệu

Binary Indexed Tree (BIT) admin - 26/02/2015 Đầu năm xả hàng, ad hướng dẫn cách giải số tập Binary Indexed Tree – BIT (bài Dãy nghịch Dĩa nhạc 3) BIT biểu diễn mảng có dạng sau: Tổng quát, đặt m = 2k.p (với p số lẻ) Hay nói cách khác, k vị trí bít bên phải m Trong BIT, nút có số hiệu m nút gốc gồm 2k nút có số hiệu từ m- 2k+1 đến m Ví dụ: - = 23.1, nút gốc nút 1, 2, 3, …, - 12 = 22.3, 12 nút gốc nút 9, 10, 11, 12 - 10 = 21.5, 10 nút gốc nút 9, 10 - = 20.7, nút gốc nút - 16 = 24.1, 16 nút gốc nút 1, 2, 3, …, 16 Trong BIT, nút gốc đại diện cho tất nút Ý nghĩa từ đại diện thường dùng nút gốc lưu tổng giá trị nút Vì tính toán, ta cần truy xuất nút gốc đủ mà không cần thiết phải truy xuất đến nút Xét ví dụ: Cho mảng gồm n phần tử a1, a2, …, an Hãy tính tổng Am = a1 + a2 + … + am (m ≤ n) Thay sử dụng vòng lặp từ đến m để truy xuất phần tử (độ phức tạp O(m)), ta sử dụng cấu trúc BIT sau: - t1 = a1 - t2 = a1 + a2 - t3 = a3 - t4 = a1 + a2 + a3 + a4 - t5 = a5 - t6 = a5 + a6 - t7 = a7 - t8 = a1 + a2 + a3 + a4+ a5 + a6 + a7 + a8 -… - t12 = a9 + a10 + a11 + a12 - (tiếp tục theo cách xây dựng BIT) * Để tính A15 (m=15), thay phải duyệt từ a1 đến a15, ta cần tính t8 + t12 + t14 + t15 * Để tính A10, cần tính t8 + t10 * Để tính A13, cần tính t8 + t12 + t13 * Để tính A16, lấy giá trị t16 Tổng quát với m bất kỳ, biểu diễn m thành dạng nhị phân, sau xóa bít m theo thứ tự từ phải sang trái, bước trung gian số nút cần truy xuất BIT Ví dụ, m = 13 có biểu diễn nhị phân 1101: 1) 1101 -> truy xuất nút 13 2) Xóa bít bên phải 1100 -> truy xuất nút 12 3) Xóa bít bên phải 1000 -> truy xuất nút 4) Xóa bít bên phải dừng Thao tác truy xuất nút gọi getBIT May mắn ta có cơng thức đơn giản để xóa bít bên phải dùng phép tốn AND Thủ tục getBIT sau: int getBIT(int m) { int result = 0; for(; m> 0; m &= m-1) { result += t[m]; } return result; } Độ phức tạp getBIT O(log2m) Vấn đề lại làm để xây dựng BIT trên? Cách thực ban đầu khởi tạo nút BIT Sau ứng với giá trị am cập nhật nút cha liên quan Ví dụ: - Cập nhật giá trị a5 -> cần cập nhật nút t5, nút cha t6, nút cha t8, nút cha t16,… - Cập nhật giá trị a9 -> cần cập nhật nút t9, nút cha t10, nút cha t12, nút cha t16,… - Cập nhật giá trị a4 -> cần cập nhật nút t4, nút cha t8, nút cha t16,… Tổng quát với m bất kỳ, biểu diễn m thành dạng nhị phân, cộng vào bít bên phải m ta nút cha m Ví dụ, m = có biểu diễn nhị phân 101: 1) 101 -> cập nhật nút 2) Cộng vào bít phải thành 0110 -> cập nhật nút 3) Cộng vào bít phải thành 1000 -> cập nhật nút 4) Cộng vào bít phải thành 10000 -> cập nhật nút 16 Thao tác cập nhật nút từ đến cha gọi updateBIT Ta có cơng thức đơn giản để cộng vào bít bên phải dùng phép toán AND Thủ tục updateBIT sau: void updateBIT(int m, int value) { for(; m1), ứng với thực hai thao tác: 1) Kiểm tra xem có số nhỏ (truy xuất t[ai]) 2) Cập nhật vào mảng t, nghĩa tăng phần tử từ t[ai+1] đến t[100.000], phần tử thêm Tuy nhiên thao tác việc cập nhật tổng thể độ phức tạp O(n2) Bây ta chuyển mảng t thành cấu trúc BIT Đối với thao tác dùng getBIT, thao tác dùng updateBIT Chương trình hoàn chỉnh cin>>n; for(i= 1; i>a[i]; kq = 0; for(i= n; i>= 1; i ) { kq += getBIT(a[i]); updateBIT(a[i]+1, 1); } cout

Ngày đăng: 04/02/2018, 22:35

Tài liệu cùng người dùng

Tài liệu liên quan