【左偏树】一种具有左偏性质的堆的有序二叉树。左偏性质是指,左子树的距离>=右子树的距离。距离是指,min{根节点到外节点的边数}。若某节点的左子树或者右子树为空,那么就是外节点。
【几个性质】
参见IOI2005 黄源河的论文
【操作】
维护若干个堆,实现插入、删除已知节点(最小值)、合并堆。logN。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<algorithm> 5 using namespace std; 6 7 /* 8 支持合并,插入,删除最小值三个操作。 9 后两个操作可以看做第一个操作的拓展。 10 */ 11 const int maxn = 10000; 12 struct tree{ 13 int l,r , v, dis, f; 14 }heap[maxn]; 15 int cnt; 16 int merge(int a, int b) 17 { 18 if (a == 0) 19 return b; 20 if (b == 0) 21 return a; 22 if (heap[a].v < heap[b].v) swap(a, b);//大堆 23 heap[a].r = merge(heap[a].r, b); 24 heap[heap[a].r].f = a; 25 if (heap[heap[a].l].dis < heap[heap[a].r].dis) 26 swap(heap[a].l, heap[a].r); 27 if (heap[a].r == 0) 28 heap[a].dis = 0; 29 else 30 heap[a].dis = heap[heap[a].r].dis + 1; 31 return a; 32 } 33 int pop(int a) 34 { 35 int l = heap[a].l; 36 int r = heap[a].r; 37 heap[l].f = l; 38 heap[r].f = r; 39 heap[a].l = heap[a].r = heap[a].dis = 0; 40 return merge(l, r); 41 } 42 int find(int a) 43 { 44 return heap[a].f == a? a: find(heap[a].f); 45 } 46 int MakeNew(int value) 47 { 48 heap[++cnt].v = value; 49 heap[cnt].l = heap[cnt].r = 0; 50 heap[cnt].f = cnt; 51 heap[cnt].dis = 0; 52 return cnt; 53 } 54 //插入到rt代表的堆中 55 int insert(int value,int rt) 56 { 57 int ret = MakeNew(value); 58 merge(ret, rt); 59 } 60 //删除已知节点x 61 int del(int x) 62 { 63 int q = heap[x].f; 64 int p = merge(heap[x].l, heap[x].r); 65 heap[p].f = q; 66 if (q!=x && heap[q].l == x){ 67 heap[q].l = p; 68 } 69 if (q!=x && heap[q].r == x){ 70 heap[q].r = p; 71 } 72 while (q!=heap[q].f) 73 { 74 if (heap[heap[q].l].dis < heap[heap[q].r].dis){ 75 swap(heap[q].l, heap[q].r); 76 } 77 if (heap[heap[q].r].dis == heap[q].dis) 78 return q; 79 heap[q].dis = heap[heap[q].r].dis + 1; 80 p = q; 81 q = heap[p].f; 82 } 83 84 } 85 int main() 86 { 87 88 return 0; 89 }