来源:互联网 发布:交友软件哪个好 编辑:程序博客网 时间:2024/06/05 23:42

        堆简单说就是可以插入删除节点的一个求最值的工具,非常好用的一个工具,我们在线面放几道题来练习一下堆(大水题!!)

最小的n个和:

题目描述 Description

有两个长度为 N 的序列 A 和 B,在 A 和 B 中各任取一个数可以得到 N^2 个和,求这N^2 个和中最小的 N个。

输入描述 Input Description

第一行输入一个正整数N;第二行N个整数Ai 且Ai≤10^9;第三行N个整数Bi,
且Bi≤10^9

输出描述 Output Description

输出仅一行,包含 n 个整数,从小到大输出这 N个最小的和,相邻数字之间用
空格隔开。

样例输入 Sample Input

5

1 3 2 4 5 
6 3 4 1 7

样例输出 Sample Output

2 3 4 4 5

数据范围及提示 Data Size & Hint

【数据规模】 对于 100%的数据,满足 1≤N≤100000。

思路:我们将b数组排升序,然后将a中的每一个数指向b数组的第一个数,将和放入堆,每次取走根的元素,给相应的a数组到b数组的映射加1,然后把新的和放入堆中,维护一下,n此操作后就可以了。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,a[1000001],b[1000001],heap[1000001],c[1000001],d[100001];void put(int x){int now,next;heap[0]+=1;heap[heap[0]]=x;now=heap[0];while(now>1){next=now>>1;if(heap[now]>=heap[next]) break;swap(heap[now],heap[next]);swap(d[now],d[next]);now=next;}}void get(){int now=1,next;while(now*2<=heap[0]){next=now<<1;if(next<heap[0]&&heap[next]>heap[next|1]) next+=1;if(heap[now]<heap[next]) break;swap(heap[now],heap[next]);swap(d[now],d[next]);now=next;}}int main(){int i,j;scanf("%d",&n);for(i=1;i<=n;++i)  scanf("%d",&a[i]);for(i=1;i<=n;++i)  scanf("%d",&b[i]);sort(b+1,b+n+1);    for(i=1;i<=n;++i)      c[i]=1;    for(i=1;i<=n;++i){    d[i]=i;        put(a[i]+b[c[i]]);}    for(i=1;i<=n;++i){    printf("%d ",heap[1]);    c[d[1]]+=1;heap[1]=a[d[1]]+b[c[d[1]]];    get();    }}


1052 地鼠游戏

题目描述 Description

    王钢是一名学习成绩优异的学生,在平时的学习中,他总能利用一切时间认真高效地学习,他不但学习刻苦,而且善于经常总结、完善自己的学习方法,所以他总能在每次考试中得到优异的分数,这一切很大程度上是由于他是一个追求效率的人。

    但王钢也是一个喜欢玩的人,平时在学校学习他努力克制自己玩,可在星期天他却会抽一定的时间让自己玩一下,他的爸爸妈妈也比较信任他的学习能力和学习习惯,所以在星期天也不会象其他家长一样对他抓紧,而是允许他在星期天上午可以自由支配时间。

    地鼠游戏是一项需要反应速度和敏捷判断力的游戏。游戏开始时,会在地板上一下子冒出很多地鼠来,然后等你用榔头去敲击这些地鼠,每个地鼠被敲击后,将会增加相应的游戏分值。问题是这些地鼠不会傻傻地等你去敲击,它总会在冒出一会时间后又钻到地板下面去(而且再也不上来),每个地鼠冒出后停留的时间可能是不同的,而且每个地鼠被敲击后增加的游戏分值也可能是不同,为了胜出,游戏参与者就必须根据每个地鼠的特性,有选择地尽快敲击一些地鼠,使得总的得分最大。

这个极具挑战性的游戏王钢特别喜欢,最近他经常在星期天上午玩这个游戏,慢慢地他不但敲击速度越来越快(敲击每个地鼠所需要的耗时是1秒),而且他还发现了游戏的一些特征,那就是每次游戏重新开始后,某个地鼠冒出来后停留的时间都是固定的,而且他记录了每个地鼠被敲击后将会增加的分值。于是,他在每次游戏开始后总能有次序地选择敲击不同的地鼠,保证每次得到最大的总分值。

输入描述 Input Description

    输入包含3行,第一行包含一个整数n1<=n<=100)表示有n个地鼠从地上冒出来,第二行n个用空格分隔的整数表示每个地鼠冒出后停留的时间,第三行n个用空格分隔的整数表示每个地鼠被敲击后会增加的分值(<=100)。每行中第i个数都表示第i个地鼠的信息。

输出描述 Output Description

    输出只有一行一个整数,表示王钢所能获得的最大游戏总分值。

样例输入 Sample Input

5

5  3  6  1  4

7  9  2  1  5

样例输出 Sample Output

24


#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,a[1000][101]={0},heap[101]={0},c[101],d[101],maxn=0,ans=0;void put(int x){int now,next;heap[0]+=1;heap[heap[0]]=x;now=heap[0];while(now>1){next=now>>1;if(heap[now]<heap[next]) break;swap(heap[now],heap[next]);now=next;}}int get(){if(!heap[0]) return 0;int m=heap[1],now=1,next;heap[1]=heap[heap[0]];heap[0]-=1;while(now*2<=heap[0]){next=now<<1;if(next<heap[0]&&heap[next]<heap[next|1]) next+=1;if(heap[now]>heap[next]) return m;swap(heap[now],heap[next]);now=next;}return m;}int main(){int i,j;scanf("%d",&n);for(i=1;i<=n;++i)  scanf("%d",&c[i]);for(i=1;i<=n;++i)  scanf("%d",&d[i]);for(i=1;i<=n;++i){a[c[i]][0]+=1;a[c[i]][a[c[i]][0]]=d[i];maxn=max(maxn,c[i]);}for(i=maxn;i>=1;--i){for(j=1;j<=a[i][0];++j)   put(a[i][j]);ans+=get();}printf("%d\n",ans);}


3377 打水

题目描述 Description

你和你的同学们在体育馆里练习,总共有 n 个人。这时大家口渴了,想要喝水。体育馆里
没有打水的地方,于是大家找到了周边的一家饭店,里面有 m 个相同的水龙头可供打水。
在这里,同一个水龙头在同一时间只能供一个人打水,第 i 个人打水所花的时间为 t[i]。
由于店老板按时间收费,所以请你求出所有人打完水所花的最小时间(水龙头的切换时间
忽略不计)。

输入描述 Input Description

第一行,n 和 m。
第二行,共 n 个数,分别是 t[1]到 t[n]。

输出描述 Output Description

第一行,一个数,即所有人打完水所花的最小时间。

样例输入 Sample Input

16 7

1 2 3 3 4 4 5 5 5 6 7 8 9 9 10 10

样例输出 Sample Output

13

数据范围及提示 Data Size & Hint

【输入输出解释】
(描述格式为 水龙头号码:在这里打水的每个人所花的时间)
1:1+5+7=13
2:2+5+6=13
3:3+10=13
4:3+10=13
5:4+9=13
6:4+9=13
7:5+8=13

 

【数据范围】
对于 30%的数据,n<=10,000,m<=1,000;
对于全部的数据,1<=n<=1,000,000,1<=m<=100,000。


#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,m,a[1000001],heapma[1000001],c[100001],d[100001],heapmi[100001];void putma(int x){int now,next;heapma[0]+=1;heapma[heapma[0]]=x;now=heapma[0];while(now>1){next=now>>1;if(heapma[now]<heapma[next]) break;swap(heapma[now],heapma[next]);now=next;}}int getma(){int m=heapma[1],next,now=1;heapma[1]=heapma[heapma[0]];heapma[0]-=1;while(now*2<=heapma[0]){next=now<<1;if(next<heapma[0]&&heapma[next]<heapma[next|1]) next+=1;if(heapma[now]>heapma[next]) return m;swap(heapma[now],heapma[next]);now=next;}return m;}void insert(){int now=1,next;while(now*2<=heapmi[0]){next=now<<1;if(next<heapmi[0]&&heapmi[next]>heapmi[next|1]) next+=1;if(heapmi[now]<heapmi[next]) break;swap(heapmi[now],heapmi[next]);now=next;}}void putmi(int x){int now,next;heapmi[0]+=1;heapmi[heapmi[0]]=x;now=heapmi[0];while(now>1){next=now>>1;if(heapmi[now]>heapmi[next]) break;swap(heapmi[now],heapmi[next]);now=next;}}int main(){int i,j,x;scanf("%d%d",&n,&m);for(i=1;i<=n;++i){    scanf("%d",&a[i]);    putma(a[i]);}for(i=1;i<=m;++i){x=getma();putmi(x);}for(;i<=n;++i){x=getma();heapmi[1]+=x;insert();}sort(heapmi+1,heapmi+m+1);cout<<heapmi[m]<<endl;}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小孩每天都是脓鼻涕怎么办 夏天小孩咳嗽流黄脓鼻涕怎么办? 受凉了流清鼻涕怎么办 宝宝50多天鼻塞怎么办 50多天孩子咳嗽怎么办 2岁宝宝伤风鼻塞怎么办 2个月伤风鼻塞怎么办 3个月宝宝鼻塞怎么办 感冒治好后咳嗽一直不好怎么办 天气太热感冒了怎么办 3个月的婴儿鼻塞怎么办 四个月宝宝感冒鼻塞严重怎么办 4个月小孩鼻塞怎么办 4个多月的宝宝流鼻涕怎么办 4个月大的宝宝流鼻涕怎么办 两岁宝宝着凉了怎么办 7岁儿童晚上鼻塞怎么办 儿童感冒鼻塞怎么办速效办法 7岁儿童感冒鼻塞怎么办 七个月婴儿感冒流鼻涕怎么办 婴儿感冒流鼻涕怎么办速效办法 三个月婴儿感冒咳嗽流鼻涕怎么办 五个月婴儿感冒咳嗽流鼻涕怎么办 两个多月的宝宝鼻塞怎么办 3个月宝宝感冒鼻塞怎么办 2个月宝宝感冒鼻塞怎么办 5个月宝宝鼻塞怎么办 6个月宝宝鼻塞怎么办 3个月婴儿感冒咳嗽怎么办 感冒打喷嚏打不出来怎么办 4岁宝宝体温37.5怎么办 8个月的宝宝鼻塞怎么办 4个月婴儿鼻塞怎么办 我一躺下就鼻塞怎么办 感冒了鼻子堵了怎么办 感冒鼻涕流的多怎么办 小孩感冒鼻塞怎么办最简单方法 鼻子痒老打喷嚏流鼻涕怎么办 眼睛红痒鼻子流鼻涕怎么办 19个月宝宝流鼻血怎么办 9个月宝宝流鼻血怎么办