Struktur data untuk peta pada interval

11

Biarkan menjadi bilangan bulat, dan biarkan menunjukkan set semua bilangan bulat. Biarkan menunjukkan interval bilangan bulat .nZ[a,b]{a,a+1,a+2,,b}

Saya mencari struktur data untuk mewakili peta . Saya ingin struktur data mendukung operasi berikut:f:[1,n]Z

  • get(i) harus mengembalikan .f(i)

  • set([a,b],y) harus memperbarui sehingga , yaitu, memperbarui ke peta baru sedemikian rupa sehingga f ( i ) = y untuk i [ a , b ] dan f ( i ) = f ( i ) untuk i [ a , b ] .ff(a)=f(a+1)==f(b)=yfff(i)=yi[a,b]f(i)=f(i)i[a,b]

  • stab(i) harus mengembalikan interval terbesar sedemikian sehingga dan konstan pada (yaitu, ).[a,b]i[a,b]f[a,b]f(a)=f(a+1)==f(b)

  • add([a,b],δ) harus memperbarui ke peta baru sedemikian rupa sehingga untuk dan untuk .fff(i)=f(i)+δi[a,b]f(i)=f(i)i[a,b]

Saya ingin masing-masing operasi ini menjadi efisien. Saya akan menghitung waktu atau sebagai efisien, tetapi waktu terlalu lambat. Tidak apa-apa jika waktu berjalan diamortisasi waktu berjalan. Apakah ada struktur data yang secara bersamaan membuat semua operasi ini efisien?O(1)O(lgn)O(n)

(Saya perhatikan pola yang sama muncul dalam beberapa tantangan pemrograman. Ini adalah generalisasi yang cukup untuk semua masalah tantangan tersebut.)

DW
sumber
Saya kira pohon merentang adalah titik awal. addakan linear dalam jumlah subinterval meskipun; Pernahkah Anda berpikir tentang pohon hamparan dengan simpul " + δ " tambahan yang belum dipadatkan, dipadatkan dengan malas? [a,b]+δ
Gilles 'SO- berhenti menjadi jahat'
Pertimbangkan sehingga f ( i ) f ( j ) untuk semua i , j . Maka Anda harus memiliki n nilai disimpan di suatu tempat. Performing set ( [ a , b ] , y ) harus menyingkirkan nilai-nilai itu entah bagaimana (dengan menulis ulang atau membuangnya - Anda dapat menunda dengan GC, tetapi Anda harus melakukan operasi O ( n ) di beberapa titik) . Dengan demikian, operasi akan menjadi O ( n ) .ff(i)f(j)ijnset([a,b],y)O(n)O(n)
avakar
@avakar, saya akan senang dengan solusi yang memperlakukan GC secara efektif "gratis". Secara lebih umum, saya akan senang dengan solusi di mana waktu berjalan diamortisasi waktu berjalan (sehingga biaya GC dapat diamortisasi dalam biaya menciptakan nilai di tempat pertama).
DW
Anda mencatat bahwa waktu konstan dan logaritmik efisien, dan waktu linier lambat. Apakah waktu terlalu lambat untuk kebutuhan Anda? O(nlgn)
jbapple
@ jbapple, hei, ini awal! Saya pikir itu layak didokumentasikan sebagai jawaban.
DW

Jawaban:

4

Saya percaya waktu logaritmik untuk semua pertanyaan dapat dicapai. Gagasan utamanya adalah menggunakan pohon interval, di mana setiap node di pohon sesuai dengan interval indeks. Saya akan membangun ide-ide kunci dengan memulai dengan versi yang lebih sederhana dari struktur data (yang dapat mendukung pengaturan dan bukan operasi lainnya), kemudian menambahkan fitur untuk mendukung fitur-fitur lainnya juga.

Skema sederhana (mendukung dapatkan dan atur, tetapi tidak menambah atau menusuk)

Katakanlah bahwa interval adalah datar jika fungsi f adalah konstan pada [ a , b ] , yaitu, jika f ( a ) = f ( a + 1 ) = = f ( b ) .[a,b]f[a,b]f(a)=f(a+1)==f(b)

Struktur data sederhana kami akan menjadi pohon interval. Dengan kata lain, kita memiliki pohon biner, di mana setiap node bersesuaian dengan interval (indeks). Kami akan menyimpan interval di setiap simpul v pohon. Setiap daun akan sesuai dengan interval datar, dan mereka akan diatur sehingga membacakan daun kiri-ke-kanan memberi kita urutan interval datar berturut-turut yang terpisah dan yang penyatuan semua [ 1 , n ] . Interval untuk simpul internal adalah penyatuan interval kedua anaknya. Juga, di setiap simpul daun kami akan menyimpan nilai V ( )I(v)v[1,n]V()dari fungsi pada interval I ( ) yang sesuai dengan simpul ini (perhatikan bahwa interval ini datar, sehingga f konstan pada interval tersebut, jadi kami hanya menyimpan nilai tunggal f di setiap simpul daun).fI()ff

Secara ekuivalen, Anda dapat membayangkan bahwa kita mempartisi ke dalam interval datar, dan kemudian struktur data adalah pohon pencarian biner di mana kunci adalah titik akhir kiri dari interval tersebut. Daun mengandung nilai f pada beberapa rentang indeks di mana f adalah konstan.[1,n]ff

Gunakan metode standar untuk memastikan bahwa pohon biner tetap seimbang, yaitu kedalamannya adalah (di mana m menghitung jumlah daun saat ini di pohon). Tentu saja, m n , jadi kedalaman selalu paling banyak O ( lg n ) . Ini akan sangat membantu di bawah ini.O(lgm)mmnO(lgn)

Kami sekarang dapat mendukung operasi get dan set sebagai berikut:

  • mudah: kita melintasi pohon untuk menemukan daun yang intervalnya berisi i . Ini pada dasarnya hanya melintasi pohon pencarian biner. Karena kedalamannya adalah O ( lg n ) , waktu lari adalah O ( lg n ) .get(i)iO(lgn)O(lgn)

  • lebih rumit. Ini berfungsi seperti ini:set([a,b],y)

    1. Pertama, kami menemukan interval daun mengandung a ; jika a 0 < a , maka kita membagi interval daun ini menjadi dua interval [ a 0 , a - 1 ] dan [ a , b 0 ] (sehingga mengubah simpul daun ini menjadi simpul internal dan memperkenalkan dua anak).[a0,b0]aa0<a[a0,a1][a,b0]

    2. Selanjutnya, kami menemukan interval daun mengandung b ; jika b < b 1 , kami membagi interval daun ini menjadi dua interval [ a 1 , b ] dan [ b + 1 , b 1 ] (sehingga mengubah simpul daun ini menjadi simpul internal dan memperkenalkan dua anak).[a1,b1]bb<b1[a1,b][b+1,b1]

    3. Pada titik ini, saya mengklaim bahwa interval dapat dinyatakan sebagai penyatuan terpisah dari interval O ( lg n ) yang sesuai dengan beberapa subset dari simpul O ( lg n ) di pohon. Jadi, hapus semua turunan dari simpul tersebut (ubah menjadi daun) dan tetapkan nilai yang disimpan di simpul tersebut menjadi y .[a,b]O(lgn)O(lgn)y

    4. Akhirnya, karena kami memodifikasi bentuk pohon, kami akan melakukan rotasi yang diperlukan untuk menyeimbangkan kembali pohon (menggunakan teknik standar apa pun untuk menjaga keseimbangan pohon).

    O(lgn)O(lgn)O(lgn)

O(lgn)O(lgmin(n,s))s

Menambahkan dukungan untuk tambah

Kami dapat memodifikasi struktur data di atas sehingga juga dapat mendukung operasi penambahan. Secara khusus, alih-alih menyimpan nilai fungsi dalam daun, itu akan direpresentasikan sebagai jumlah angka yang disimpan dalam satu set node.

f(i)iivV(v)v0,v1,,vkvkI(vk)V(v0)++V(vk)

xx

add([a,b],δ)[a,b]O(lgn)O(lgn)δO(lgn)node. (Kami tidak menghapus keturunan mereka.)

O(lgn)O(lgmin(n,s))s

Mendukung operasi penikaman

Permintaan penusukan adalah yang paling menantang untuk didukung. Gagasan dasarnya adalah mengubah struktur data di atas untuk mempertahankan invarian tambahan berikut:

I()

[a,b][a,b][a,b]a,b1aabbn[a,b]=[a,b][a,b]

Ini membuat operasi tusukan mudah diimplementasikan:

  • stab(i)i

ff12=O(1)O(lgn)

O(lgn)O(lgmin(n,s))s

Berpisah pikiran

Fiuh, ini skema yang cukup rumit. Saya harap saya tidak membuat kesalahan. Silakan periksa pekerjaan saya dengan cermat sebelum mengandalkan solusi ini.

DW
sumber