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;