P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G

题目链接 https://www.luogu.com.cn/problem/P1090

这题前几天一看到这个数据范围就把我重复排序的想法pass了。。。。

刚巧下午学了堆和哈夫曼树,所以想到这题不就是用小根堆解嘛?直接模板了。

然后看到标签里优先队列这四个认识又不认识的大字....当时学校在上数据结构的时候只记得有循环队列,没有提到过优先队列啊。

(吆西,我最喜欢学新东西了)

最后,一道没有思路的题变成了一道不想写的题变成了一道水题(?)


 

优先队列 AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,x,ans;
 4 priority_queue<int,vector<int>,greater<int>>q;
 5 int main()
 6 {
 7     cin>>n;
 8     for(int i=1;i<=n;i++)
 9     {
10         cin>>x;
11         q.push(x);
12     }
13     while(q.size()>=2)
14     {
15         int a=q.top(); q.pop();
16         int b=q.top(); q.pop();
17         ans+=a+b;
18         q.push(a+b);
19     }
20     cout<<ans;
21     return 0;
22 }

 

dalao手写的堆:(其实也是就是堆的模板了)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=10000+10;
 4 int n,heap[maxn],size=0;
 5 void up(int p) //二叉小根堆向上调整(子节点小于父节点就调整)
 6 {
 7     while(p>1)
 8     {
 9         if(heap[p]<heap[p/2])
10         {
11             swap(heap[p],heap[p/2]);
12             p/=2;
13         }
14         else break;
15     }
16 }
17 void insert(int val) //二叉堆插入,新元素放在堆底,向上调整
18 {
19     heap[++size]=val;
20     up(size);
21 }
22 void down(int p) //二叉小根堆向下调整
23 {
24     int s=p*2;
25     while(s<=size)
26     {
27         //下面这句话是从左右儿子中选一个更小的做交换
28         if(s<size&&heap[s+1]<heap[s]) s++;
29         if(heap[s]<heap[p])
30         {
31             swap(heap[s],heap[p]);
32             p=s;
33             s=p*2;
34         }
35         else break;
36     }
37 }
38 void extract() //二叉堆删除堆顶
39 {
40     heap[1]=heap[size--]; //将堆底移至堆顶,向下调整
41     down(1);
42 }
43 int gettop() //返回堆顶的值
44 {
45     return heap[1];
46 }
47 int main()
48 {
49     cin>>n;
50     for(int i=1; i<=n; i++)
51     {
52         int a;
53         cin>>a;
54         insert(a); //建立二叉堆
55     }
56     long long ans=0; //其实这里不会越界,但好像原题数据是3万
57     while(size>=2) //如果还可合并
58     {
59         int top1=gettop(); //取出堆顶(堆中最小值)后删除堆顶
60         extract();
61         int top2=gettop(); //同上
62         extract();
63         ans+=(top1+top2);
64         insert(top1+top2); //将两数之和加入二叉堆,重复运算
65     }
66     cout<<ans<<endl; //输出答案
67     return 0;

 

posted @ 2022-04-11 23:01  爱吃虾滑  阅读(167)  评论(0)    收藏  举报