XCPC第五站!Trie树+并查集+堆,字符串和数字,你想要的全都有!( 三 )


2.向上调整
向上调整的过程中只需要和自己当前的父节点比较 。如果比父节点都小 , 那么就肯定小于等于兄弟节点了 。
3.具体操作(以下heap下标从1开始 , 这样可以保证2k为左儿子 , 2k+1为右儿子)
(1)插入数据
把新的数据插入到堆的最后一个位置 。假如我们用size表示堆的大小 , x表示新数据 , heap表示堆 , 那么伪代码为heap[++size] = x , 然后再让从size处开始up , 即up(size)) 。
(2)获取最小数
就是heap[1] 。
(3)删除最小值
用整个堆的最后一个元素覆盖堆顶的元素 , 让size– , 再down(1)就OK 。
(4)删除任意一个元素
比如要删除第k个位置的值 , 同样是让最后一个位置的值去覆盖它 , 即heap[k] = heap[size] , 让size–然后再down(k) , up(k)即可 。(因为无外乎是变大或者变小两种情况 , 若变小 , 会执行up;若变大 , 会执行down 。这样虽然写了两个函数 , 但是只会执行一个 , 但可以避免分类讨论)
(5)修改任意一个元素
比如要修改第k个位置的值 , 像上面一样的道理 , heap[k] = x , up(k),down(k)即可(也是只会执行一个函数) 。
问题:怎么建堆呢?我们当然可以采取一个一个数插入的方法 , 但这样做的时间复杂度是O(nlogn) 。下面我们介绍一种O(n)的算法——向下调整 。由于最后一层是最大的 , 不需要再down , 而且最后一层约有n/2个元素 , 因此我们只需要从n/2开始往前down直到1即可 。
#includeusing namespace std;const int N = 1e5+10;int heap[N],num;void down(int k){//记录当前编号int t = k;//不要以为这里暂时有t = k就写heap[2*k]
下面我们实现up向上调整操作 。
【XCPC第五站!Trie树+并查集+堆,字符串和数字,你想要的全都有!】void up(int k){//只要父节点存在并且比当前节点大就交换while(k/2>0&&heap[k/2]>h[k]){swap(heap[k/2],heap[k]);k/=2;}}