堆可以看成一个近似的完全二叉树,其任何一非叶节点满足性质:
Key[i]<=key[2i+1]&&Key[i]<=key[2i+2](小根堆)
或者
Key[i]>=Key[2i+1]&&key[i]>=key[2i+2](大根堆)
有了上面的定义,就有下面的计算:
#define Pa(i) i>>1 //父亲
#define Le(i) i<<1 //左儿子
#define Ri(i) (i<<1)+1 //右儿子
接下来是维护堆的性质:
一个新的i到堆中。(大根堆)
void
Mh(
int
i){
int
l=Le(i),r=Ri(i),lag;
if
(l<=num && heap[i]<heap[l]) lag=l;
else
lag=i;
if
(r<=num && heap[lag]<heap[r]) lag=r;
if
(lag!=i) {
swap(heap[i],heap[lag]);
Mh(lag);
}
}
实现插入操作:
void
Hik(
int
i,
int
key){
heap[i]=key;
while
(i>1 && heap[Pa(i)].d<heap[i].d){
swap(heap[Pa(i)],heap[i]);
i=Pa(i);
}
}
删除最大值:
void
Hem(){
if
(num<1) {
printf
(
"none\n"
);
return
;
}
heap[1]=heap[num];
num--; Mh(1);
return
;
}
这些是最基本的堆操作,其他操作可以根据这些推出。
但我们一般不手写,因为STL中有priority_queue。
priority_queue<int>que;默认大根堆。
priority_queue<int, vector<int>, greater<int>> que; 小根堆。(#include<functional>//需要用到greater)
或
struct cmp{
bool operator()(int x, int y){
return x > y; //x越小优先级越高
}
};
priority_queue<int, vector<int>, cmp>que;//这个声明要特别注意两点:vector<int>和cmp
或
struct node{
int x, y;
friend bool operator<(node a, node b){//标准库默认使用 < 来确认它们的关系,换成>就不行了哦
return a.y>b.y;//>表示越小越优先,<表示越大越优先
} //可以这样记:最大堆与小于号有关,最小堆与大于号有关。这样记会不会好一点呢。。。
};
priority_queue<node> que;
操作:
que.push();
que.top();
que.pop();
还有映射堆:
两个堆互相标记:
来个题吧:
小明的账单
时间限制: 1 Sec 内存限制: 128 MB
题目描述
小明在一次聚会中,不慎遗失了自己的钱包,在接下来的日子,面对小明的将是一系列的补卡手续和堆积的账单。。。
在小明的百般恳求下,老板最终同意延缓账单的支付时间。可老板又提出,必须从目前还没有支付的所有账单中选出面额最大和最小的两张,并把他们付清。还没有支付的账单会被保留到下一天。
请你帮他计算出支付的顺序。
输入
第1 行:一个正整数N(N≤15,000),表示小明补办银联卡总共的天数。
第2 行到第N+1 行:每一行描述一天中收到的帐单。先是一个非负整数M<=100,表示当天
收到的账单数,后跟M个正整数(都小于1,000,000,000),表示每张帐单的面额。
输入数据保证每天都可以支付两张帐单。
输出
输出共N 行,每行两个用空格分隔的整数,分别表示当天支付的面额最小和最大的支
票的面额。
样例输入
4
3 3 6 5
2 8 2
3 7 1 7
0
样例输出
3 6
2 8
1 7
5 7
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 #define Pa(i) i>>1 8 #define Le(i) i<<1 9 #define Ri(i) (i<<1)+1 10 #define oo 1000000000 11 int size1,size2; 12 struct node{ 13 int d,t; 14 } heap_max[2000000],heap_min[2000000]; 15 void Max_h(int i){ 16 int l=Le(i),r=Ri(i),lag; 17 if (l<=size1 && heap_max[i].d<heap_max[l].d) lag=l; 18 else lag=i; 19 if (r<=size1 && heap_max[lag].d<heap_max[r].d) lag=r; 20 if (lag!=i) { 21 heap_min[heap_max[i].t].t=lag; 22 swap(heap_max[i],heap_max[lag]); 23 return Max_h(lag); 24 } 25 } 26 void Min_h(int i){ 27 int l=Le(i),r=Ri(i),lag; 28 if (l<=size2 && heap_min[i].d>heap_min[l].d) lag=l; 29 else lag=i; 30 if (r<=size2 && heap_min[lag].d>heap_min[r].d) lag=r; 31 if (lag!=i) { 32 heap_max[heap_min[i].t].t=lag; 33 swap(heap_min[i],heap_min[lag]); 34 return Min_h(lag); 35 } 36 } 37 void Hik_max(int i,int key){ 38 heap_max[i].d=key; 39 while (i>1 && heap_max[Pa(i)].d<heap_max[i].d){ 40 heap_min[heap_max[i].t].t=Pa(i); 41 swap(heap_max[Pa(i)],heap_max[i]); 42 i=Pa(i); 43 } 44 } 45 void Hik_min(int i,int key){ 46 heap_min[i].d=key; 47 while (i>1 && heap_min[Pa(i)].d>heap_min[i].d){ 48 heap_max[heap_min[i].t].t=Pa(i); 49 swap(heap_min[Pa(i)],heap_min[i]); 50 i=Pa(i); 51 } 52 } 53 void Mhi(int a){ 54 size1++; heap_max[size1].d=-oo; heap_max[size1].t=size2+1; 55 size2++; heap_min[size2].d=oo; heap_min[size2].t=size1; 56 Hik_max(size1,a); Hik_min(size2,a); 57 } 58 void Hem(){ 59 printf("%d %d\n",heap_min[1].d,heap_max[1].d); 60 int mint=heap_max[1].t,maxt=heap_min[1].t; 61 heap_min[mint]=heap_min[size2]; 62 size2--; Min_h(1); 63 heap_max[maxt]=heap_max[size1]; 64 size1--; Max_h(1); 65 heap_min[1]=heap_min[size2]; 66 size2--; Min_h(1); 67 heap_max[1]=heap_max[size1]; 68 size1--; Max_h(1); 69 return; 70 } 71 int main() 72 { 73 int n; scanf("%d",&n); 74 while (n--){ 75 int nu; scanf("%d",&nu); 76 for (int i=1;i<=nu;i++) { 77 int a; scanf("%d",&a); 78 Mhi(a); 79 } 80 Hem(); 81 } 82 }