算法导论随笔(二)
标签:lse def 优先 https bre 小根堆 收获 大根堆 scan
算法导论随笔(二)
手动建堆
- 作为stl选手,对于手写堆接触较少,不过熟悉建堆的过程还是有不少收获的。
- 堆的载体:一个长度为n的数组
- 基本操作:维持某节点的堆性质
void heapify(int o) //维护i号节点的堆性质
{
while (1)
{
int ls = o
for (int i = (n1 >> 1); i >= 1; --i)
{
heapify(i);
}
void modify(int o, int v) //内部函数,将mh[o]改为v
{
if ((v 1 && (mh[o] > 1]) ^ fl)
{
sw(mh[o], mh[o >> 1]);
o >>= 1;
}
}
else
{
mh[o] = v;
heapify(o);
}
}
应用:手写优先队列 luogu1168
- 经典题,求出序列前奇数个数的中位数,可以使用平衡树来做,不过更简单的是用两个优先队列。大根堆存前k / 2 + 1小的数,小根堆存剩下的k / 2个数,每次输出大根堆顶就可以。
应用代码:
#include
#include
#include
#include
#define INF 2147483647
using namespace std;
int aa[100005], n;
void sw(int& a, int& b)
{
int t = a;
a = b;
b = t;
}
struct minh
{
int mh[100005];
bool fl = false; //默认小根堆
int n1 = 0;
void set(int f) //设置大小根堆
{
bool r = f ^ fl;
fl = f;
if (r) //如果变化则更新堆
{
for (int i = (n1 >> 1); i >= 1; --i)
{
heapify(i);
}
}
}
void heapify(int o) //维护i号节点的堆性质
{
while (1)
{
int ls = o 1 && (mh[o] > 1]) ^ fl)
{
sw(mh[o], mh[o >> 1]);
o >>= 1;
}
}
else
{
mh[o] = v;
heapify(o);
}
}
int top() //查询
{
return mh[1];
}
void push(int v) //插入
{
mh[++n1] = fl ? -INF : INF;
modify(n1, v);
}
int pop() //带返回值的pop
{
int v = -INF;
if (n1)
{
v = mh[1];
mh[1] = mh[n1--];
heapify(1);
}
return v;
}
int size() //堆大小
{
return n1;
}
} q1, q2;
int main()
{
q1.n1 = q2.n1 = 0;
q1.set(0);
q2.set(1);
scanf("%d", &n);
int xx;
scanf("%d", &xx);
printf("%d\n", xx);
q2.push(xx);
for (int i = 2; i xx)
{
q1.push(tmp);
q2.pop();
q2.push(xx);
}
else
{
q1.push(xx);
}
}
}
return 0;
}
算法导论随笔(二)
标签:lse def 优先 https bre 小根堆 收获 大根堆 scan
原文地址:https://www.cnblogs.com/int-me-X/p/14280006.html
文章来自:
搜素材网的
编程语言模块,转载请注明文章出处。
文章标题:
算法导论随笔(二)
文章链接:http://soscw.com/index.php/essay/61145.html
评论