堆——练习题
……堆是一个很好用的东西,但遗憾的是,在oi混了三年多的我居然到现在才会……惭愧惭愧……
堆可以在O(log n) 的时间内查询最大值和最小值,非常好用的一个数据结构,本人认为比优先队列快得多……只是本人观点……
手写堆:不好写……没写过……反正c++有stl库(等到了左偏树再学……)
stl堆:感谢c++有stl这种省时省力的好东西,要是noip开放所有库并允许o2 o3优化就更好了(退役之前不用想了)
stl堆函数:
make_heap:将一个数组建堆,例:对a[1]到a[100]建堆:make_heap(a+1,a+1+100)(可添加comp)
pop_heap:将堆顶元素弹出,弹到……一般是堆底,例:将上边的堆堆顶弹到堆底:pop_heap(a+1,a+1+n)(可添加comp)
push_heap:将堆底(一般是)元素弹到堆顶,例:把上面的再弹回来:push_heap(a+1,a+1+n)(可添加comp)
sort_heap:堆排序,其实很少用,我没用过……好像用一下就不是一个正常的堆了……,例:sort_heap(a+1,a+1+n)(可添加comp)
comp函数的注意事项:
……就一个:如果是要建大根堆,就return a<b;建小根堆return a>b;其实默认是大根堆……
例题1:
合并果子:
题意:百度上有…………………………………………………………………………我好不负责任……
思路:看完题意就会了……………………………………………………………………
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<algorithm> 8 #include<vector> 9 #include<map> 10 #include<set> 11 using namespace std; 12 int n,ans=0,a[10024]={0}; 13 bool cmp(int e,int t){ 14 if(e<t) return false; 15 return true; 16 } 17 int main(){ 18 // freopen("goods.in","r",stdin); 19 // freopen("goods.out","w",stdout); 20 scanf("%d",&n); 21 for(int i=0;i<n;i++) scanf("%d",&a[i]); 22 make_heap(a,a+n,cmp); 23 for(int i=n;i>1;i--){ 24 pop_heap(a,a+i,cmp); 25 pop_heap(a,a+i-1,cmp); 26 a[i-2]=a[i-2]+a[i-1]; 27 ans=ans+a[i-2]; 28 push_heap(a,a+i-1,cmp); 29 } 30 cout<<ans<<endl; 31 // fclose(stdin); 32 // fclose(stdout); 33 return 0; 34 }
例2:
序列合并
题意:给两个序列a,b, 两个序列中的数非递减,两个序列长度都为n,求最小的n个(a[i]+b[j]),不可重复。
数据范围:n:1---100000;
输入格式:
n
a[1] a[2] a[3]……a[n]
b[1] b[2] b[3]……b[n]
输出格式:
n个数,用空格隔开……
样例:
输入:3
2 6 6
1 4 8
输出:3 6 7
思路:
因为 a[1]+b[i]<=a[2]+b[i]<=a[3]+b[i]……
所以先将 a[1]+b[1],a[1]+b[2],a[1]+b[3]……a[1]+b[n]存入堆,进行n次操作,每次操作:
1.取出堆中最小值,放入答案
2.用下一个数取代这个最小值,放入堆(如:如果堆最小值为a[1]+b[1],那么就放入a[2]+b[1];如果堆最小值为a[42]+b[323],那么就放入a[43]+b[323])
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<string> 4 #include<cmath> 5 #include<algorithm> 6 #include<iostream> 7 using namespace std; 8 9 10 int a[200000],b[200000],n; 11 int ans[200000],m; 12 struct ad{ 13 int sum; 14 int xv; 15 int hao; 16 }c[200000]; 17 18 bool cmp(const ad a,const ad b){ 19 return a.sum>b.sum; 20 } 21 22 int main(){ 23 scanf("%d ",&n); 24 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 25 for(int i=1;i<=n;i++) scanf("%d",&b[i]); 26 for(int i=1;i<=n;i++) c[i].sum=a[1]+b[i]; 27 for(int i=1;i<=n;i++) c[i].hao=i; 28 for(int i=1;i<=n;i++) c[i].xv=1; 29 make_heap(c+1,c+1+n,cmp); 30 while(m<n){ 31 pop_heap(c+1,c+1+n,cmp); 32 m++; 33 ans[m]=c[n].sum; 34 c[n].xv++; 35 c[n].sum=a[c[n].xv]+b[c[n].hao]; 36 push_heap(c+1,c+1+n,cmp); 37 } 38 for(int i=1;i<=n;i++) printf("%d ",ans[i]); 39 return 0; 40 }