Cấu trúc dữ liệu cho bản đồ theo các khoảng


11

Đặt là số nguyên và để biểu thị tập hợp tất cả các số nguyên. Đặt biểu thị khoảng của các số nguyên .nZ[a,b]{a,a+1,a+2,,b}

Tôi đang tìm kiếm một cấu trúc dữ liệu để thể hiện bản đồ . Tôi muốn cấu trúc dữ liệu hỗ trợ các hoạt động sau:f:[1,n]Z

  • get(i) sẽ trả về .f(i)

  • set([a,b],y) nên cập nhật sao cho , tức là cập nhật lên bản đồ mới sao cho cho và cho .ff(a)=f(a+1)==f(b)=yfff(i)=yi[a,b]f(i)=f(i)i[a,b]

  • stab(i) sẽ trả về khoảng lớn nhất sao cho và không đổi trên (tức là ).[a,b]i[a,b]f[a,b]f(a)=f(a+1)==f(b)

  • add([a,b],δ) nên cập nhật lên bản đồ mới sao cho cho và cho .f f ( i ) = f ( i ) + δ i [ a , b ] f ( i ) = f ( i ) i [ a , b ]fff(i)=f(i)+δi[a,b]f(i)=f(i)i[a,b]

Tôi muốn mỗi hoạt động này có hiệu quả. Tôi sẽ tính thời gian hoặc là hiệu quả, nhưng thời gian quá chậm. Không sao nếu thời gian chạy được khấu hao thời gian chạy. Có một cấu trúc dữ liệu đồng thời làm cho tất cả các hoạt động này hiệu quả?O ( lg n ) O ( n )O(1)O(lgn)O(n)

(Tôi đã nhận thấy một mô hình tương tự xuất hiện trong một vài thử thách lập trình. Đây là một khái quát có thể đủ cho tất cả các vấn đề thách thức đó.)


Tôi đoán cây splay là điểm khởi đầu. addsẽ là tuyến tính trong số lượng các khoảng con của ; Bạn đã nghĩ về một cây splay có thêm các nút Unary , được nén gọn gàng chưa? + δ[a,b]+δ
Gilles 'SO- ngừng trở nên xấu xa'

Xét sao cho cho tất cả , . Sau đó, bạn phải có giá trị được lưu trữ ở đâu đó. Performing có để thoát khỏi những giá trị nào đó (bằng cách viết lại chúng hoặc vứt đi - bạn có thể trì hoãn với GC, nhưng bạn sẽ phải làm hoạt động Ở một vài điểm). Như vậy, hoạt động sẽ là . f ( i ) f ( j ) i j n đặt ( [ a , b ] , y ) O ( n ) O ( n )ff(i)f(j)ijnset([a,b],y)O(n)O(n)
avakar

@avakar, tôi sẽ rất vui với giải pháp coi GC là "miễn phí" một cách hiệu quả. Tổng quát hơn, tôi sẽ hài lòng với giải pháp trong đó thời gian chạy được khấu hao thời gian chạy (do đó chi phí của GC có thể được khấu hao trong chi phí tạo ra giá trị ở vị trí đầu tiên).
DW

Bạn lưu ý rằng thời gian không đổi và logarit là hiệu quả và thời gian tuyến tính là chậm. Thời gian có quá chậm so với nhu cầu của bạn không? O(nlgn)
jbapple

@jbapple, này, đó là một sự khởi đầu! Tôi nghĩ rằng đó là giá trị tài liệu như một câu trả lời.
DW

Câu trả lời:


4

Tôi tin rằng thời gian logarit cho tất cả các truy vấn là có thể đạt được. Ý tưởng chính là sử dụng một cây khoảng, trong đó mỗi nút trong cây tương ứng với một khoảng của các chỉ số. Tôi sẽ xây dựng các ý tưởng chính bằng cách bắt đầu với một phiên bản cấu trúc dữ liệu đơn giản hơn (có thể hỗ trợ get và set nhưng không phải các hoạt động khác), sau đó thêm các tính năng để hỗ trợ các tính năng khác.

Một lược đồ đơn giản (hỗ trợ get và set, nhưng không thêm hoặc đâm)

Nói rằng một khoảng là phẳng nếu hàm là hằng số trên , ví dụ, nếu .f[a,b]ff ( một ) = f ( một + 1 ) = = f ( b )[a,b]f(a)=f(a+1)==f(b)

Cấu trúc dữ liệu đơn giản của chúng tôi sẽ là một cây khoảng. Nói cách khác, chúng ta có một cây nhị phân, trong đó mỗi nút tương ứng với một khoảng (của các chỉ số). Chúng tôi sẽ lưu trữ khoảng tương ứng trong mỗi nút của cây. Mỗi chiếc lá sẽ tương ứng với một khoảng phẳng và chúng sẽ được sắp xếp sao cho việc đọc các lá từ trái sang phải cho chúng ta một chuỗi các khoảng phẳng liên tiếp tách rời nhau và có liên kết là tất cả . Khoảng cho một nút bên trong sẽ là sự kết hợp giữa các khoảng của hai con của nó. Ngoài ra, trong mỗi nút lá chúng ta sẽ lưu trữ giá trị của hàm trên khoảngv [ 1 ,I(v)vV ( ) f Tôi ( ) f f[1,n]V()fI()tương ứng với nút này (lưu ý rằng khoảng này là phẳng, vì vậy là hằng số trên khoảng, vì vậy chúng ta chỉ lưu trữ một giá trị trong mỗi nút lá).ff

Tương tự, bạn có thể tưởng tượng rằng chúng ta phân vùng thành các khoảng phẳng và sau đó cấu trúc dữ liệu là một cây tìm kiếm nhị phân trong đó các khóa là điểm cuối bên trái của các khoảng đó. Các lá chứa giá trị của tại một số chỉ số trong đó không đổi.f f[1,n]ff

Sử dụng các phương pháp tiêu chuẩn để đảm bảo rằng cây nhị phân vẫn cân bằng, nghĩa là độ sâu của nó là (trong đó đếm số lượng lá hiện tại trong cây). Tất nhiên, , vì vậy độ sâu luôn luôn nhiều nhất là . Điều này sẽ hữu ích dưới đây.m m n O ( lg n )O(lgm)mmnO(lgn)

Bây giờ chúng tôi có thể hỗ trợ các hoạt động get và set như sau:

  • i O ( lg n ) O ( lg n )get(i) rất dễ: chúng ta đi ngang qua cây để tìm chiếc lá có khoảng chứa . Điều này về cơ bản chỉ là đi qua một cây tìm kiếm nhị phân. Vì độ sâu là , thời gian chạy là .iO(lgn)O(lgn)

  • set([a,b],y) phức tạp hơn. Nó hoạt động như thế này:

    1. Đầu tiên, chúng tôi tìm thấy khoảng lá có chứa ; nếu , thì chúng ta chia khoảng thời gian lá này thành hai khoảng và (do đó biến nút lá này thành một nút bên trong và giới thiệu hai con).a a 0[a0,b0]a[ a 0 , a - 1 ] [ a , b 0 ]a0<a[a0,a1][a,b0]

    2. Tiếp theo, chúng tôi tìm thấy khoảng lá có chứa ; nếu , chúng tôi chia khoảng thời gian lá này thành hai khoảng và (do đó biến nút lá này thành một nút bên trong và giới thiệu hai con).b b < b 1 [ a 1 , b ] [ b + 1 , b 1 ][a1,b1]bb<b1[a1,b][b+1,b1]

    3. Tại thời điểm này, tôi cho rằng khoảng có thể được biểu thị dưới dạng liên kết rời rạc của các khoảng tương ứng với một số tập hợp con của các nút trong cây. Vì vậy, xóa tất cả hậu duệ của các nút đó (biến chúng thành lá) và đặt giá trị được lưu trữ trong các nút đó thành .O ( lg n ) O ( lg n ) y[a,b]O(lgn)O(lgn)y

    4. Cuối cùng, vì chúng tôi đã sửa đổi hình dạng của cây, chúng tôi sẽ thực hiện bất kỳ phép quay cần thiết nào để cân bằng lại cây (sử dụng bất kỳ kỹ thuật tiêu chuẩn nào để giữ cho cây cân bằng).

    Vì thao tác này bao gồm một vài thao tác đơn giản trên các nút (và tập hợp các nút đó có thể dễ dàng tìm thấy trong thời gian ), nên tổng thời gian cho thao tác này là .O ( lg n ) O ( lg n )O(lgn)O(lgn)O(lgn)

Điều này cho thấy rằng chúng tôi có thể hỗ trợ cả thao tác get và set trong thời gian cho mỗi thao tác. Trong thực tế, thời gian chạy có thể được hiển thị là , trong đó là số lượng thao tác thiết lập được thực hiện cho đến bây giờ.O ( lg phút ( n , s ) ) sO(lgn)O(lgmin(n,s))s

Thêm hỗ trợ để thêm

Chúng ta có thể sửa đổi cấu trúc dữ liệu trên để nó cũng có thể hỗ trợ thao tác thêm. Cụ thể, thay vì lưu trữ giá trị của hàm trong các lá, nó sẽ được biểu diễn dưới dạng tổng của các số được lưu trữ trong một tập hợp các nút.

Chính xác hơn, giá trị của hàm ở đầu vào sẽ có thể được phục hồi dưới dạng tổng của các giá trị được lưu trữ trong các nút trên đường dẫn từ gốc của cây xuống lá có khoảng . Trong mỗi nút chúng ta sẽ lưu trữ một giá trị ; nếu đại diện cho tổ tiên của một chiếc lá (bao gồm cả chính chiếc lá), thì giá trị của hàm tại sẽ là .i i v V ( v ) v 0 , v 1 , ... , v k v kf(i)iivV(v)v0,v1,,vkvkI(vk)V(v0)++V(vk)

Thật dễ dàng để hỗ trợ các hoạt động get và set bằng cách sử dụng một biến thể của các kỹ thuật được mô tả ở trên. Về cơ bản, khi chúng ta đi ngang qua cây, chúng ta theo dõi tổng giá trị đang chạy, để cho mỗi nút mà truy cập ngang qua, chúng ta sẽ biết tổng giá trị của các nút trên đường dẫn từ gốc đến . Khi chúng tôi thực hiện điều đó, các điều chỉnh đơn giản để thực hiện get và set được mô tả ở trên sẽ đủ.xx

Và bây giờ chúng tôi có thể hỗ trợ cách hiệu quả. Đầu tiên, chúng ta biểu thị khoảng là liên kết của các khoảng tương ứng với một số tập hợp các nút trong cây (tách một nút ở điểm cuối bên trái và điểm cuối bên phải nếu cần ), chính xác như được thực hiện trong các bước 1-3 của thao tác thiết lập. Bây giờ, chúng ta chỉ cần thêm vào giá trị được lưu trữ trong mỗi nút . (Chúng tôi không xóa con cháu của họ.)[ a , b ] O ( lg nadd([a,b],δ)[a,b]O(lgn)O(lgn)δO(lgn)

Điều này cung cấp một cách để hỗ trợ get, set và thêm thời gian cho mỗi thao tác. Trong thực tế, thời gian chạy cho mỗi hoạt động là trong đó đếm số lượng hoạt động đã đặt cộng với số lượng hoạt động thêm.O(lgn)O(lgmin(n,s))s

Hỗ trợ hoạt động đâm

Các truy vấn đâm là thách thức nhất để hỗ trợ. Ý tưởng cơ bản sẽ là sửa đổi cấu trúc dữ liệu trên để duy trì bất biến bổ sung sau:

(*) Khoảng tương ứng với mỗi lá là khoảng phẳng tối đa.I()

Ở đây tôi nói rằng một khoảng là khoảng phẳng tối đa nếu (i) bằng phẳng và (ii) không có khoảng nào chứa là phẳng (nói cách khác, với tất cả thỏa mãn , hoặc hoặc không bằng phẳng).[ một , b ] [ một , b ] một ' , b ' 1 một 'một b b 'n [ một ' , b '[a,b][a,b][a,b]a,b1aabbn[a,b]=[a,b][a,b]

Điều này làm cho thao tác đâm dễ thực hiện:

  • stab(i) tìm lá có khoảng chứa và sau đó trả về khoảng đó.i

Tuy nhiên, bây giờ chúng ta cần sửa đổi tập hợp và thêm các hoạt động để duy trì bất biến (*). Mỗi lần chúng ta chia một chiếc lá thành hai, chúng ta có thể vi phạm bất biến nếu một số cặp lá liền kề có cùng giá trị của hàm . May mắn thay, mỗi thao tác set / add thêm tối đa 4 khoảng thời gian lá mới. Ngoài ra, với mỗi khoảng thời gian mới, bạn có thể dễ dàng tìm thấy khoảng thời gian lá ngay bên trái và bên phải của nó. Do đó, chúng ta có thể biết liệu bất biến có bị vi phạm hay không; nếu có, thì chúng ta hợp nhất các khoảng liền kề trong đó có cùng giá trị. May mắn thay, việc hợp nhất hai khoảng liền kề không kích hoạt thay đổi xếp tầng (vì vậy chúng tôi không cần kiểm tra xem liệu sáp nhập có thể đưa ra các vi phạm bổ sung về bất biến hay không). Trong tất cả, điều này liên quan đến việc kiểm traf 12 = O ( 1 ) O ( lg n )ff12=O(1)cặp khoảng và có thể hợp nhất chúng. Cuối cùng, do việc sáp nhập làm thay đổi hình dạng của cây, nếu điều này vi phạm các bất biến cân bằng, hãy thực hiện bất kỳ phép quay cần thiết nào để giữ cho cây cân bằng (theo các kỹ thuật tiêu chuẩn để giữ cho cây nhị phân cân bằng). Tổng cộng, công việc này bổ sung tối đa công việc bổ sung cho các hoạt động thiết lập / thêm.O(lgn)

Do đó, cấu trúc dữ liệu cuối cùng này hỗ trợ tất cả bốn hoạt động và thời gian chạy cho mỗi hoạt động là . Ước tính chính xác hơn là thời gian cho mỗi thao tác, trong đó đếm số lượng tập hợp và thêm hoạt động.O (O(lgn)sO(lgmin(n,s))s

Chia tay suy nghĩ

Phew, đây là một kế hoạch khá phức tạp. Tôi hy vọng tôi đã không phạm sai lầm. Vui lòng kiểm tra công việc của tôi một cách cẩn thận trước khi dựa vào giải pháp này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.