Czasy (na herze) dla struktur danych (wszystkie testy odpalone sprawdzarką dude'a):
Struktura | Czas |
---|---|
RBT (drx, c++) | 25.81 s |
SkipList (ekg2, C) | 29.09 s |
AVL (dude, C) | 32 s |
AVL (tr) | 32.98 s |
Ja mam na RBT i działa szybko. Podejrzewam, że AVL działałyby podobnie szybko (AVL mają wysokość <1.44log(n) vs <2log(n) RBT; mają więc szybszy Upper i Lower, ale wolniejszy Insert i Delete) jeśli rozkład I+U jest podobny jak U+L, co zależy od testów.
Swoją drogą ciekawią mnie drzewa van Emde Boasa, które mają operacje słownikowe w O(log log n). Co prawda ilość elementów jest mała – maksymalnie 50000; log(50000) = 15.6, ale log(36) = 5.2, więc drzewa vEB mogą być nawet sześć razy szybsze. — drx 2010/05/23 18:16
Moje (dj3500) i Damiana czasy, testowane za pomocą:
time for i in `seq 1 10`; do ./program < test$i.in > test$i.tempout; done
Struktura | Czas |
---|---|
Treap (dj3500, c++) | 27.31 s |
Splay (DS, c++) | 39.34 s |
RBT z STLa (dj3500, c++) | 28.04 s |
trwałe RBT (dj3500, ocaml, dostaje głównie TLE, wyłazi też poza 4MB) | 61.24 s |
Warto też może nadmienić, że treap ma 102 linijki, a cały program 3.5 kB kodu więc jeśli nie widać różnicy to po co przepłacać ;) dj3500
http://www.ii.uni.wroc.pl/~mbi/dyd/aisd_10s/wyniki_E.html - wyniki
0 oznacza brak poprawnej odpowiedzi na jakiś test
pierwsza kolumna to suma czasów
11304: Mik Kali 13336: Kon Wypy 13492: Luk Syno 14248: Luk Zapa 14272: Pio Pole 14444: Krz Kusi 14484: Daw Jurc 14620: Mar Ocze 14824: Mic Karp 15028: Wik Jana 15060: Mag Sara 15128: Kac Krol 15188: And Kaje 15204: Pio Bzow 15260: Paw Muri 15460: Dam Rusa 15500: Krz Parj 15696: Krz Ziel (test) 15716: Kar Kona 15848: Jak Tarn 15960: Pio Posa 16008: Mar Kola 16100: Dam Stra 16160: Pio Krze 16312: Pio Ryba 16408: Dan Blas 16828: Krz Nowi 16884: Krz Ziel 17036: Iza Bicz 17440: Mar Janu 17468: Pio Rzep 17936: Mic Mazu 18008: Adr Dyli 18052: Paw Kacp 18408: Pio Gajo 18660: Mic Roza 19072: Pio Walk 19932: Mac Maty 26812: Mic Soko 0: Ark Goch 0: Raf Kowa 0: Mic Kras 0: Dam Piąt 0: Mac Wiec 0: Ada Kacz 0: Ale Gali 0: Bla Sala 0: Dam Wiec 0: Dom Brul 0: Dom Rusa 0: Fil Slom 0: J L (test) 0: Kam Miel 0: Luc Fran 0: Luk Toma 0: Luk Wrza 0: Mac Pacu 0: Mar Janc 0: Pat Urba 0: Paw Kali 0: Paw Kime 0: Sla Step 0: Szy Lasz 0: Tom Luch 0: Wal Augu (test)
#include <stdio.h> #define SEARCH_BRAK (2LL<<60) #define MAX_ELEMS 50010 #define LMAX 1000000000L typedef signed long long T; inline void putll (T & x) { signed long l = x / LMAX, r = x % LMAX; if (l != 0) printf("%ld%09ld\n", l,(r<0)?-r:r); else printf("%ld\n", r); } typedef struct node { T data; int prio; struct node *left, *right, *up; } node; node * root; /* Własny alokator pamięci. */ unsigned short nextFreeBlock[MAX_ELEMS]; // następna wolna komórka za bieżącą wolną (0 to kolejna) node Block[MAX_ELEMS]; // pula pamięci unsigned short firstFreeBlock = 1; // bo zero to specjalna wartosc unsigned int index; #define allocate(X) X = &Block[firstFreeBlock]; \ if (nextFreeBlock[firstFreeBlock] == 0) \ firstFreeBlock++; \ else \ firstFreeBlock = nextFreeBlock[firstFreeBlock]; #define free(X) index = X - &Block[0]; \ nextFreeBlock[index] = firstFreeBlock; \ firstFreeBlock = index; /****/ inline void rotate_left (node * n) { node *x = n->right; x->up = n->up; if (x->up != NULL) { if (x->up->left == n) x->up->left = x; else x->up->right = x; } n->right = x->left; if (n->right != NULL) n->right->up = n; n->up = x; x->left = n; } inline void rotate_right (node * n) { node *x = n->left; x->up = n->up; if (x->up != NULL) { if (x->up->left == n) x->up->left = x; else x->up->right = x; } n->left = x->right; if (n->left != NULL) n->left->up = n; n->up = x; x->right = n; } void ins (T & e) { T ret = 0; node *n = root, *p = NULL; static int next = 1; // p - ojciec e while (n != NULL) { p = n; ret = e - (n->data); if (ret < 0) n = n->left; else if (ret > 0) n = n->right; else return; // duplikat } allocate(n); n->left = n->right = NULL; n->up = p; n->data = e; if (p == NULL) root = n; else if (ret < 0) p->left = n; else p->right = n; next = next * 1103515245 + 12345; n->prio = (unsigned)(next/65536) % 32768; // rebalance while (n->up != NULL && (n->up->prio) > (n->prio)) if (n->up->right == n) rotate_left (n->up); else rotate_right (n->up); if (n->up == NULL) root = n; } void del (T & e) { node *n = NULL, *m = root; // znajdź poprzednika e - n. while (m != NULL) if (e < m->data) m = m->left; else { n = m; m = m ->right; } if ((n == NULL) || (n->data != e)) { fputs_unlocked ("BRAK\n", stdout); return; } /* rotuj do liścia */ while (n->left != NULL || n->right != NULL) { if (n->left != NULL) { if (n->right == NULL || n->left->prio < n->right->prio) rotate_right (n); else rotate_left (n); } else rotate_left (n); if (root == n) root = n->up; } if (n->up == NULL) root = NULL; else if (n->up->left == n) n->up->left = NULL; else n->up->right = NULL; free(n); fputs_unlocked ("OK\n", stdout); } inline void lower (node * t, T & k) { T ret = SEARCH_BRAK; while (t != NULL) { if (t->data == k) { putll (k); return; } if (k < t->data) t = t->left; else { ret = t->data; t = t->right; } } if (ret == SEARCH_BRAK) fputs_unlocked ("BRAK\n", stdout); else putll ( ret); } inline void upper (node * t, T & k) { T ret = SEARCH_BRAK; while (t != NULL) { if (t->data == k) { putll ( k); return; } if (k < t->data) { ret = t->data; t = t->left; } else t = t->right; } if (ret == SEARCH_BRAK) fputs_unlocked ("BRAK\n", stdout); else putll ( ret); } int main (void) { setvbuf (stdout, NULL, _IOFBF, 2 << 10); T sign, n; char op, ch; int oper; root = NULL; oper = getchar_unlocked() - '0'; while ((ch = getchar_unlocked ()) >= '0') oper = oper * 10 + (ch - '0'); while (oper --> 0) { sign = 1; n = 0; op = getchar_unlocked (); // operacja getchar_unlocked (); // spacja ch = getchar_unlocked (); if (ch == '-') sign = -1; else n = ch - '0'; while ((ch = getchar_unlocked ()) >= '0') n = n * 10 + (ch - '0'); n *= sign; switch (op) { case 'I': ins (n); break; case 'D': del (n); break; case 'L': lower (root, n); break; default: upper (root, n); } } return 0; }