网上题解是普通的堆合并,都是用优先队列直接做的。可是正解的堆合并应该是用左偏堆或者斐波那契堆的吧,不然O(X * N ^ 2)的复杂度应该是过不了的。斐波那契堆的实现相对麻烦,所以我用了左偏堆完成这题,最坏复杂度O(X * N log N)。
这题就是一个模拟,没什么可以解释的。1y~
代码如下:
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <string> 6 7 using namespace std; 8 9 template<class T> 10 struct Node { 11 int d; 12 T dt; 13 Node *l, *r; 14 Node() { l = r = NULL;} 15 Node(T dt) : dt(dt), d(0) { l = r = NULL;} 16 } ; 17 18 template<class T> 19 Node<T> *merge(Node<T> *a, Node<T> *b) { 20 if (!a) return b; 21 if (!b) return a; 22 if (a->dt < b->dt) return merge(b, a); 23 a->r = merge(a->r, b); 24 a->d = a->r ? a->r->d + 1 : 0; 25 return a; 26 } 27 28 template<class T> 29 Node<T> *popTop(Node<T> *x) { Node<T> *ret = merge(x->l, x->r); delete x; return ret;} 30 31 template<class T> 32 struct Leftist { 33 Node<T> *rt; 34 void clear() { rt = NULL;} 35 T top() { return rt->dt;} 36 void push(T dt) { rt = merge(rt, new Node<T>(dt));} 37 void pop() { rt = popTop(rt);} 38 } ; 39 40 const int N = 11111; 41 typedef pair<int, string> PIS; 42 Leftist<PIS> pq[N]; 43 char buf[111]; 44 45 int main() { 46 int n, m; 47 while (~scanf("%d%d", &n, &m)) { 48 int k, x, y; 49 for (int i = 1; i <= n; i++) { 50 pq[i].clear(); 51 scanf("%d", &k); 52 for (int j = 0; j < k; j++) { 53 scanf("%s%d", buf, &x); 54 pq[i].push(PIS(-x, buf)); 55 } 56 } 57 for (int i = 0; i < m; i++) { 58 scanf("%s%d", buf, &x); 59 if (!strcmp(buf, "GETOUT")) { 60 puts(pq[x].top().second.c_str()); 61 pq[x].pop(); 62 } 63 if (!strcmp(buf, "JOIN")) { 64 scanf("%d", &y); 65 pq[x].rt = merge(pq[x].rt, pq[y].rt); 66 pq[y].rt = NULL; 67 } 68 if (!strcmp(buf, "GETON")) { 69 scanf("%s%d", buf, &y); 70 pq[x].push(PIS(-y, buf)); 71 } 72 } 73 } 74 return 0; 75 }
——written by Lyon