洛谷P1090-合并果子-题解
2016-11-12 22:21
190 查看
合并果子
Hello 大家好,我是CSDN新来的一名……小小的OI选手,刚开通了博客,比较激动233,所以先献上一次题解那么下面切入正题(为什么不能开头空两个郁闷)
首先献上题目地址
https://www.luogu.org/problem/show?pid=1090
就是这么一道题了,目(keng)测(ding)很多大神都写过,不喜勿喷~
题目分析
很明显的贪心了,每次选两个最小的拿出来求和累加在放回去,直到只剩一堆为止然后估计所有人一开始看到都是这样想的(手写的有语法错误请谅解哈)
for (int i=1;i<=n;i++) scanf("%d",&a[i]); do { sort(a,a+1+n,cmp); ans+=(a +a[n-1]); a[n-1]+=a ; n--; }while (n>1)
然后一看n到10000 我就怂(zhi zhang)了,于是就引入了神奇的someting
堆
大神肯定司空见惯了,如果有新手的话还是略微解释一下
一棵二叉树,保证根节点一定最优,其两个孩子次优,以此类推
因为是二叉树所以更改和删除都是logn的。
大根堆就是根节点最大,反之亦然
再回到这题,容易发现,可以把n个数建成一个小跟堆,每次用logn的时间取出2个最小值,累加到ans里面,再合并放回去
要做n-1次嘛,每次logn,故复杂度为O(nlogn),也就过了,毕竟1W还是很小的,那么下面献上程序咯
#include <cstdio> #include <iostream> #include <cstring> using namespace std; int f[10001]; int ans,len,n; int get() { return f[1]; } void remove() { int son,next; f[1]=f[len--]; son=1; while (son*2<=len) { next=son*2; if (next<len && f[next+1]<f[next]) next++; if (f[son]<f[next])break; swap(f[next],f[son]); son=next; } } void put(int x) { int son,next; f[++len]=x; son=len; while (son>1) { next=son>>1; if (f[son]>=f[next]) break; swap(f[son],f[next]); son=next; } } int main() { len=0; scanf("%d",&n); int x; memset(f,0,sizeof(f)); for (int i=1;i<=n;i++) { scanf("%d",&x); put(x); } ans=0; while (len>1) { int t1=get(); remove(); int t2=get(); remove(); int t3=t1+t2; //printf("%d %d %d\n",t1,t2,t3); put(t3); ans+=t3; } printf("%d",ans); return 0; }
这道题也就过了,然而是手写堆,比较烦,容易错什么的,于是就有了stl库的优先队列这种interesting的东西,就是满足出队的总是最优,所以就可以写优先队列了,用上stl库,加个头文件
#include <quene>
具体用法抱歉本蒟蒻还没用用过,用过给大家下一题的时候补上
**
谢谢
**相关文章推荐
- 洛谷P1090 合并果子
- 洛谷 P1090 合并果子
- 【堆】洛谷 P1090 合并果子
- 洛谷-P1090 合并果子
- 洛谷 P1090 合并果子
- 洛谷 P1090 合并果子
- [NOIP2004] 提高组 洛谷P1090 合并果子
- 洛谷 P1090 合并果子
- [洛谷 P1090]合并果子 --- 手打二叉堆
- 18-03-09 P1090 合并果子
- 【基础练习】【堆】codevs1063 合并果子题解
- P1090 合并果子
- [luogu]P1090合并果子-插入排序的简单应用
- 洛谷1090 合并果子
- NOIP 2004 合并果子 题解 (堆 )
- 合并果子 (codevs 1063) 题解
- CodeVS 1063 合并果子 题解
- P1090 合并果子 <优先队列>
- 【学术篇】一石三鸟的——洛谷2654——原核生物培养(石子合并果子)
- Luogu-p1090 合并果子(优先队列)