【数据结构】堆
堆
模拟堆
目的
- 插入一个数
x - 输出当前集合中的最小值
- 删除当前集合的最小值
- 删除第
k个插入的数 - 修改第
k个插入的数,将其变为x
实现
struct modheap
{
int h[N],ph[N],hp[N],idx=0,len=0;
void heap_swap(int a,int b)
{
swap(h[a],h[b]);
swap(hp[a],hp[b]);
swap(ph[hp[a]],ph[hp[b]]);
}
void down(int x)
{
int t = x;
if(x*2<=len&&h[x*2]<h[t]) t=2*x;
if(x*2+1<=len&&h[x*2+1]<h[t]) t=2*x+1;
if(t!=x)
{
heap_swap(t,x);
down(t);
}
}
void up(int x)
{
if(x/2&&h[x/2]>h[x])
{
heap_swap(x/2,x);
up(x>>1);
}
}
void insert(int x)
{
len++,idx++;
h[len]=x;
ph[idx]=len,hp[len]=idx;
up(len);
}
int get()
{
return h[1];
}
void del_mi()
{
heap_swap(1,len);
len--;
down(1);
}
void del_kth(int k)
{
int u = ph[k];
heap_swap(u,len);
len--;
up(u);down(u);
}
void mod_kth(int k,int x)
{
h[ph[k]]=x;
up(ph[k]);down(ph[k]);
}
};
对顶堆
目的
动态维护中位数
实现原理
对顶堆,一个是小根堆,另一个是大根堆。假设 g 是大根堆,l 是小根堆,那么观察下图不难发现,两堆中间的元素,左边都是小于它的,且 g.top() 是小于它的最大值,右边都是大于它的,且 l .top() 是大于它的最小值。
实现
struct midheap
{
priority_queue<int> g;
priority_queue<int,vector<int>,greater<int>> l;
void insert(int x)
{
if(!g.size()||x<g.top()) g.push(x);
else l.push(x);
if(g.size()>l.size()+1) l.push(g.top()),g.pop();
if(l.size()>g.size()+1) g.push(l.top()),l.pop();
}
//若出现偶数个,且中间两个不同的情况,则该get获得的是较大的
//若想得到较小的,则将>改为>=
int get()
{
return g.size() > l.size() ? g.top() : l.top();
}
};
可删除堆
目的
可以完成删除堆内指定元素。
实现原理
我们建一个临时堆,如果要删除哪个元素,就把哪个元素压入临时堆,然后待此元素和正常堆的堆顶元素相同时(即两个堆顶一样),就同时pop掉。
实现
//可删除堆
struct popheap
{
priority_queue<int> _add,_del;//其中的方向要相同,可以使大根堆也可以是小根堆
int size()
{
while(!_add.empty()&&!_del.empty()&&_add.top()==_del.top()) _add.pop(),_del.pop();
return _add.size();
}
int get()
{
while(!_add.empty()&&!_del.empty()&&_add.top()==_del.top()) _add.pop(),_del.pop();
return _add.top();
}
void add(int x)
{
_add.push(x);
}
void del(int x)
{
_del.push(x);
}
};

浙公网安备 33010602011771号