http://poj.org/problem?id=3253

经典题目了,大意是说如果要切断一个长度为a的木条需要花费代价a, 问要切出要求的n个木条所需的最小代价。

无论是以下哪种方法,最原始的思路就是从相反的角度思考,将每两个合并,花费的代价是他们两个的和,一直到最后只剩下一个

方法一:

使用STL的priority_queue,先将所有的木条放入到队列中。每次取出两个木条将他们的长度相加,加入到花费当中去,然后放回到队列中。

这样计算的时间复杂度就是O(NlogN)。

方法二:

使用单调队列,我们可以分析到,由于每次取出的都是优先队列中最小的两个,也就是首部的两个,那我们可以考虑另外借用一个数组b用来存放每次取出的两个数的和,我们注意到,每次取出来的两个数相加,得到的和也是单调递增的(这个很容易证明),可以看下面的例子:

原始状态:

a    1 3 5 6 7 8 9

b    null

第一次在a里取出两个数1,3相加,放入b中:

a    5 6 7 8 9

b    4

这里我们先从a、b两个数组队首取出一个最小的数4,再从两个数组的队首取出一个最小的数(此时b数组已经队空)5,相加后放入b:

a    6 7 8 9

b    9

同理,这次会取出6和7,相加放入b(注意每次相加的结果都是放入b中的,这里不放入a中是为了保证a和b数组的单调性):

a    8 9

b    9 13

经过几次操作后会得到:

a    null

b    39

最后a队列空,b队列只剩下一个数,这时合并就结束了

我们可以注意到,由于每次都将相加得到的和放进了b队列,所以b一定是单调递增的, 而且最后平均每个数只被使用了一次,所以它的复杂度是O(N)的。

单调队列   和   优先队列:

 #include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define lson k<<1, L, mid
#define rson k<<1|1, mid+1, R typedef long long LL;
const double eps = 1e-;
const int MAXN = ;
const int MAXM = ; int main()
{
int N, len;
while(~scanf("%d", &N))
{
priority_queue<LL, vector<LL>, greater<LL> >q;
for(int i=;i<N;i++)
{
scanf("%d", &len);
q.push((LL)len);
}
LL ans = ;
while(q.size() > )
{
LL p = q.top(); q.pop();
p += q.top(); q.pop();
ans += p;
q.push(p);
}
printf("%lld\n", ans);
}
return ;
}
 #include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define lson k<<1, L, mid
#define rson k<<1|1, mid+1, R typedef long long LL;
const double eps = 1e-;
const int MAXN = ;
const int MAXM = ; LL a[MAXN], b[MAXN]; int main()
{
int N;
while(~scanf("%d", &N))
{
mem0(b);
for(int i=;i<N;i++) scanf("%lld", &a[i]);
sort(a, a+N);
int frontA=, frontB=, rearB=, num=;
LL ans=;
while(++num<N)
{
int sum = ;
if(frontB==rearB || (frontA<N&&a[frontA]<b[frontB])) { sum += a[frontA]; frontA ++; }
else { sum += b[frontB]; frontB++; }
if(frontB==rearB || (frontA<N&&a[frontA]<b[frontB])) { sum += a[frontA]; frontA ++; }
else { sum += b[frontB]; frontB++; }
b[rearB++] = sum;
ans += sum;
}
printf("%lld\n", ans);
}
return ;
}

POJ3253Fence Repair(优先队列或单调队列)的更多相关文章

  1. luogu 2827 蚯蚓 单调队列/优先队列

    易知可利用优先队列选取最大值: 但是通过分析可知,先取出的蚯蚓分开后仍然要比后分的长,所以可直接利用单调队列找队头即可,分三个单调队列,分别找未切割,切割,切割2三种情况 #include<bi ...

  2. hdu_5884_Sort(二分+单调队列)

    题目链接:hdu_5884_Sort 题意: 有n个数,每个数有个值,现在你可以选择每次K个数合并,合并的消耗为这K个数的权值和,问在合并为只有1个数的时候,总消耗不超过T的情况下,最小的K是多少 题 ...

  3. FZU 1894 志愿者选拔 单调队列

    训练赛的题…… 暴力一波明显超时…… 最近刚学stl 感觉是优先队列 但还是太会用…… 以后可以试一下优先队列…… 比赛之后百度了一下 发现是单调队列…… 看起来挺简单的 也算个模版题吧…… 总之思路 ...

  4. 数据结构录 之 单调队列&单调栈。

    队列和栈是很常见的应用,大部分算法中都能见到他们的影子. 而单纯的队列和栈经常不能满足需求,所以需要一些很神奇的队列和栈的扩展. 其中最出名的应该是优先队列吧我觉得,然后还有两种比较小众的扩展就是单调 ...

  5. HDU 4193 Non-negative Partial Sums(想法题,单调队列)

    HDU 4193 题意:给n个数字组成的序列(n <= 10^6).求该序列的循环同构序列中,有多少个序列的随意前i项和均大于或等于0. 思路: 这题看到数据规模认为仅仅能用最多O(nlogn) ...

  6. Parade(单调队列优化dp)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others)    ...

  7. P1886 P2216 单调队列模板

    何为单调队列? 单调队列是一个队列(废话) 而且必须同时满足下标单调和值单调两个单调特性. 跟优先队列不同,优先队列直接使用堆(heap)来实现,如何删去特定下标元素?不明. 本人喜欢用单调队列存下标 ...

  8. HDU 3415 Max Sum of Max-K-sub-sequence【单调队列】

    <题目链接> 题目大意: 给你一段从1~N的圆形序列,要你求出这段圆形序列中长度不超过K的最大连续子序列之和是多少,并且输出这子序列的起点和终点. 解题分析: 既然是求连续子序列之和,我们 ...

  9. POJ 2823 Sliding Window​ (模板题)【单调队列】

    <题目链接> <转载于>>> > 题目大意: 给你一段序列和一个长为k的窗口,这个窗口从最左边逐渐向右滑,直到滑到最右边,问你,该窗口在滑动的过程中,最大值和 ...

随机推荐

  1. 51nod1406 与查询

    这题卡I/O...dp一下... #include<cstdio> #include<cstring> #include<cctype> #include<a ...

  2. 插件svn简单使用

    首先安装服务器Server 傻瓜式样操作.下一步下一步就这样完成了,选择的是个人版. 然后打开Server的图形化界面:VisualSVN Server Manager Repositories:资源 ...

  3. MIPI DSI 和 D-PHY 初始化序列

    MIPI DSI 和 D-PHY 初始化序列 -- 深圳 南山平山村 曾剑锋 参考文档: i.MX 6Dual/6Quad Multimedia Applications Processor Refe ...

  4. erl0007 - erlang 远程节点连接的两种方式

    启动连接:erl -setcookie abc -name xxx@192.168.x.x -remsh xxx@192.168.x.y 退出:ctrl + g,q 参考:http://www.cnb ...

  5. Heritrix源码分析(十三) Heritrix的控制中心(大脑)CrawlController(二)

    本博客属原创文章,欢迎转载!转载请务必注明出处:http://guoyunsky.iteye.com/blog/650744      本博客已迁移到本人独立博客: http://www.yun5u. ...

  6. mysql 表日常变化前几

    mysql 表日常变化前几use performance_schema create table test.snap1 as SELECT OBJECT_SCHEMA, OBJECT_NAME, CO ...

  7. CSS hack——不同浏览器的CSS应对法

    1.IE条件注释法: lte表示“小于等于”,“lt”表示“小于”,“gte”表示“大于等于”,“gt”表示“大于”,“!”表示“不等于”. <!--[if IE 6]> <link ...

  8. mysql初识之数据文件及其他文件

    在mysql中数据文件存放于在my.cnf中datadir指定的路径,使用的表引擎不同产生的文件格式.表文件个数也会有所差异.mysql的表引擎有多种,表的扩展名也不一样,如innodb用“ .ibd ...

  9. jsonp实现跨域访问

    要实现JSONP跨域访问,首先就要了解什么是跨域?然后JSONP与JSON的关系? 1.什么是跨域? 跨域简单的说就是一个域名下的程序和另一个域名下的程序做数据交互.比如说:现有一个http://ww ...

  10. Java文件下载的几种方式

    public HttpServletResponse download(String path, HttpServletResponse response) { try { // path是指欲下载的 ...