cuốn sách gpt4 ai đã làm

Giải thích chi tiết về cây đoạn cổ điển: từ nguyên lý đến thực hành

In lại Tác giả: Sahara Thời gian cập nhật: 25-12-2024 00:47:52 57 4
mua khóa gpt4 Nike

Phân đoạn cây là một cây dữ liệu cấu trúc rất hiệu quả được sử dụng để giải quyết các vấn đề về truy vấn và sửa đổi khoảng thời gian. quy tắc và cách thực hiện đoạn đường cây cũng như khám phá các ứng dụng kịch bản của nó.

Giới thiệu: Bài toán sửa đổi mảng khoảng trống

Trong một số cổ điển toán học, ý tưởng như cho một mảng, các phép toán sau thường được yêu cầu:

  1. Truy vấn khoảng thời gian:Truy vấn trong phạm vi định nghĩa tối nhất của mảngGiá trị tối đa, giá trị tối thiểu, tổng giá trịChờ đợi.
  2. Chỉnh sửa khoảng thời gian: Thực hiện một thao tác trên tất cả các giá trị trong một phạm vi nhất định, giả sử rằng chúng ta luôn muốn tăng Tất cả các phạm vi đều được xác định giá trị.

Thế tiến lưỡng nan của các phương pháp bạo lực

Đối với các truy vấn khoảng trống, chúng tôi có thể duyệt trực tiếp các khoảng trống để tính toán kết quả mỗi lần; thay đổi khoảng trống, chúng tôi có thể duyệt toàn bộ khoảng phụ để cập nhật. array length. Độ phức tạp về thời gian của phương pháp này là \(O(n)\). mảng lớn thì hiệu quả sẽ trở lại nên không thể được chấp nhận.

Cây đoạn thẳng ra đời.


Cấu hình và cách thực hiện đoạn đường cây

Phân đoạn cây là phân tích cây nhị phân được sử dụng để lưu trữ và xử lý khoảng thời gian thông tin một cách hiệu quả.

1. Từ khoảng đến phân tích cây nhị phân

Đoạn phân đoạn liên tục chia không có các mảng chỉ số thành nhiều khoảng và sử dụng phân tích cây nhị phân để lưu trữ thông tin của các khoảng này:

  • node lá: Đại diện cho một phần tử duy nhất của mảng.
  • local node: Biết thông tin tóm tắt của một khoảng phụ tối thiểu (chẳng hạn như khoảng tổng, giá trị lớn nhất, vv).

Ví dụ, cho mảng [1, 3, 5, 7, 9, 11], đoạn thẳng của nó như sau:

              [0, 5] / \ [0, 2] [3, 5] / \ / \ [0, 1] (2, 2) [3, 4] (5, 5) / \ / \ (0, 0) (1, 1) (3, 3)(4, 4)

Trong câu Hỏi điều này, chúng tôi lưu trữ tổng số các khoảng.

2. Độ phức tạp của không gian và mảng 4x

Bảng thông tin chỉ sử dụng 1 lần không gian và không yêu cầu dư thừa dữ liệu, khi phân tích đoạn cây nhị phân thường được biểu hiện bằng mảng. \(4n\) vì:

  1. Đoạn đoạn không có quá trình chỉnh sửa nhị phân cây \(2n - 1\).
  2. Để đảm bảo trạng thái nhanh nhất, các nút trống bên trái và bên phải của nút lá vẫn không cần xử lý đặc biệt. Để đơn giản hóa việc phát triển mã khai báo, chúng tôi phân tích trực tiếp mảng kích thước như sau. \(4n\), đảm bảo không vượt quá giới hạn và hình thành thói quen.

Tất nhiên, phức tạp của không gian là \(O(n)\) và chỉ có hệ số thay đổi. số trong ví dụ trên.

3. Triển khai mã

Xây dựng đoạn cây

Sau đây là ví dụ mã hóa để xây dựng phân đoạn cây:

#bao gồm  #bao gồm  use vector cây không có tên std;; // Phân tích cây bối rối lười; > sẽ được sử dụng sau arr ; // Dữ liệu gốc được sử dụng để xây dựng cây void build(int node, int start, int end) { if (start == end) { // Cây nút lá[node] = arr[start] ; } khác { // Các nút không có lá tiếp tục được chia thành hai phần int mid = (start + end) / 2; nút 2 * + 1; nút int right_child = 2 * nút + 2; build(right_child, mid + 1, end); tree[node] = tree[left_child] + tree[right_child] // Tổng khoảng là tổng của bên trái và bên phải} }

Truy vấn và sửa đổi khoảng thời gian

1.Truy vấn khoảng trống

Hỗ trợ đoạn đường hỗ trợ các kết quả khoảng trống truy vấn và chia bài toán thành các khoảng nhỏ để xử lý thông tin qua phương pháp chia for value. trong đoạn thẳng sau đây là mã thực thi:

int query(int node, int start, int end, int l, int r) { if (r < start || l > end) { return 0; // hoàn toàn tách rời} if (l <= start && end < = r ) { return tree[node]; // Bao gồm hoàn toàn} // If bao gồm một int mid = (bắt đầu + kết thúc) / 2; int left_sum = query(left_child, start, mid, l, r) ; truy vấn(right_child, mid + 1, end, l, r return left_sum + right_sum;

Nếu muốn sửa đổi khoảng \([1,4]\), chúng tôi có thể thấy rằng khoảng thời gian cuối cùng được chia thành nhiều khoảng phụ và Không phải lúc nào cũng đi xuống đáy, điều này giúp cải thiện đáng kể hiệu quả.

                     [0, 5][36]× / \ [0, 2][9]× [3, 5][27]× / \ / \ [0, 1][4]× (2, 2)[5] √ [3, 4][16]√ (5, 5)[11] / \ / \ (0, 0)[1] (1, 1)[3]√ (3, 3)[7] (4, 4)[9]

2. Edit one point

Những thay đổi ở đây nút bên dưới sẽ ảnh hưởng đến giá trị của nút cha và tổng sẽ được tính lại sau khi quá trình xử lý kết thúc end.

void update(int node, int start, int end, int idx, int val) { if (start == end) { tree[node] = val } else { int mid = (start + end) / 2; nút + 1; int right_child = 2 * nút + 2; if (idx <= mid) { update(left_child, start, mid, idx, val } else { update(right_child, mid + 1, end, idx, val); } cây[nút] = cây[left_child] + cây[right_child];

Vẫn sử dụng ví dụ vừa rồi, giả sử rằng giá trị của số dưới 1 đã được sửa đổi:

                     [0, 5][37]× / \ [0, 2][10]× [3, 5][27] / \ / \ [0, 1][5]× (2, 2)[5] [ 3, 4][16] (5, 5)[11] / \ / \ (0, 0)[1] (1, 1)[4]√ (3, 3)[7] (4, 4)[9]

3. Chỉnh sửa khoảng thời gian: đánh dấu ngu ngốc

Đây là phần khó nhất của đoạn cây. chuyển tiếp lười biếng. Update khi cần thiết.

Cụ thể, nếu chúng tôi muốn sửa đổi giá trị của một khoảng nhất định (ví dụ: tăng \(a\)), chúng tôi vẫn sẽ chia nó Thay vào đó, tôi chỉ sửa đổi nút này và đặt dấu lười ở nút đó thành \(a\), biết rằng tất cả các nút của tôi phải được bổ sung bằng \(a\), nhưng thực tế tôi vẫn chưa làm được điều đó. chúng tôi sẽ xóa dấu gạch ngang và đưa nó xuống một cấp.

Khai báo Mã Lai



void updateRange(int node, int start, int end, int l, int r, int val) { if (lazy[node] != 0) { tồn tại không , đẩy nó xuống một lớp cây[node] += (end - start + 1) * lười biếng[nút]; bắt đầu != end) { lười [2 * nút + 1] += lười [ nút 2 * + 2] += lười[nút]; } lười [nút] = 0; if (r < bắt đầu || l > kết thúc) { // Hoàn toàn tách return } nếu (l <= bắt đầu && kết thúc <= r) { // Đã bao gồm đầy đủ, sau đó dừng lại ở đây và sử dụng cây đánh dấu lười đỉnh [node] += (end - start + 1) * val; if (start != end) { lười [2 * nút + 1] += val ; } return; } // If được bao gồm updateRange(2 * node + 2, mid + 1, end, l, r, val); cây[nút] = cây[2 * nút + 1] + cây[2 * nút + 2 ] }

Vẫn làm theo ví dụ trên, tăng \([1,4]\) lên 1, ta thấy nó được đánh dấu tại \([3,4]\) và không còn lan truyền xuống dưới nữa. Vì vậy, việc đánh dấu ngu ngốc là bắt buộc đối với phân đoạn cây chứ không phải là một lớp phủ trên bánh.

Mặc dù giá trị của cây con tạm thời không chính xác, nhưng việc truy cập vào cây chắc chắn sẽ vượt qua dấu vết lười biếng. Đưa nó xuống, đảm bảo rằng điều đó sẽ kéo dài. khoảng trống cũng cần thêm một đoạn dấu thăng lên và xuống (tức là phần if (lazy[node] != 0)).

                     [0, 5][40]× / \ [0, 2][11]× [3, 5][29]× / \ / \ [0, 1][5]× (2, 2)[6] √ [3, 4][18|+1]√ (5, 5)[11] / \ / \ (0, 0)[1] (1, 1)[4]√ (3, 3)[7] (4, 4)[9]


Tại sao phân tích lại đoạn cây bị hủy bỏ thành công \(O(\log n)\) phần?

Chúng tôi nhận thấy rằng mỗi khi thực hiện một truy vấn hoặc sửa đổi, đường cây sẽ phân tách bằng khoảng cách cách chia đôi và cuối cùng phân tích khoảng trống thành các phân đoạn lớn khoảng log n, điều này giúp cải thiện đáng kể hiệu Ngay trong kết quả. trường hợp xấu nhất, tạo thành công phân tích cây phân tách left left and right of tree. thùng là \. (O(\log n)\).


Open width architecture

đoạn văn bản của con trỏ cây

Khi ý tưởng thuật toán hoàn toàn giống nhau, cây nhị phân cũng có thể được phát triển bằng cách sử dụng con trỏ và không trả lời use. thớt. Nhược điểm Phương pháp này sẽ không được hiển thị trong bài viết này.

Trong bản văn của bài viết này (duy trì mảng), các phiên bản của mảng mảng tĩnh hơn và được sử dụng phổ biến hơn. Nếu bạn muốn duy trì phạm vi giá trị lớn nhưng thưa thớt, phiên bản con trỏ có thể tiết kiệm rất nhiều dung lượng.


Các ứng dụng khác của đoạn đường cây

Ngoài ra, việc truy vấn và sửa đổi khoảng thời gian, phân đoạn đường cây vẫn có thể giải quyết các vấn đề sau:

  1. Tối đa thời gian của khoảng thời gian: Ngoài tổng khoảng, nút phân đoạn cây còn lưu trữ giá trị tối thiểu hoặc tối đa của khoảng. gần giống nhau. truy vấn trong nút nhánh.
  2. truy vấn k value value: Kết hợp với các thuật toán khác, có thể đạt được thông tin sắp xếp và thống kê.
  3. Đoạn đường phân đoạn 2D: Mở rộng sang vấn đề hai chiều.

Cây phân đoạn xử lý tốt các thuộc tính khoảng có thể phân tách (chẳng hạn như tổng hợp, cực đại, cực tiểu, tích, vv), nhưng đối với một số thuộc tính phi tuyến, việc xử lý này khó hoặc không có hiệu quả , một số toán về khoảng. không thể sử dụng đường phân đoạn cây. Chế độ này không thể được thực hiện bằng cách đơn giản kết hợp các kết quả của hai khoảng phụ vì nó yêu cầu tổng thông tin could. khoảng cách. Ý tưởng phân chia và chính phục của đoạn đường cây.

Cuối cùng, bài viết này về giải thích chi tiết về cây phân đoạn khoảng cổ điển: từ nguyên tắc đến thực hiện kết nối end ở đây. thực hiện, vui lòng tìm kiếm các bài viết của CFSDN hoặc. của tôi trong tương lai .

57 4 0
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress