POJ3253Fence Repair(优先队列或单调队列)
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(优先队列或单调队列)的更多相关文章
- luogu 2827 蚯蚓 单调队列/优先队列
易知可利用优先队列选取最大值: 但是通过分析可知,先取出的蚯蚓分开后仍然要比后分的长,所以可直接利用单调队列找队头即可,分三个单调队列,分别找未切割,切割,切割2三种情况 #include<bi ...
- hdu_5884_Sort(二分+单调队列)
题目链接:hdu_5884_Sort 题意: 有n个数,每个数有个值,现在你可以选择每次K个数合并,合并的消耗为这K个数的权值和,问在合并为只有1个数的时候,总消耗不超过T的情况下,最小的K是多少 题 ...
- FZU 1894 志愿者选拔 单调队列
训练赛的题…… 暴力一波明显超时…… 最近刚学stl 感觉是优先队列 但还是太会用…… 以后可以试一下优先队列…… 比赛之后百度了一下 发现是单调队列…… 看起来挺简单的 也算个模版题吧…… 总之思路 ...
- 数据结构录 之 单调队列&单调栈。
队列和栈是很常见的应用,大部分算法中都能见到他们的影子. 而单纯的队列和栈经常不能满足需求,所以需要一些很神奇的队列和栈的扩展. 其中最出名的应该是优先队列吧我觉得,然后还有两种比较小众的扩展就是单调 ...
- HDU 4193 Non-negative Partial Sums(想法题,单调队列)
HDU 4193 题意:给n个数字组成的序列(n <= 10^6).求该序列的循环同构序列中,有多少个序列的随意前i项和均大于或等于0. 思路: 这题看到数据规模认为仅仅能用最多O(nlogn) ...
- Parade(单调队列优化dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others) ...
- P1886 P2216 单调队列模板
何为单调队列? 单调队列是一个队列(废话) 而且必须同时满足下标单调和值单调两个单调特性. 跟优先队列不同,优先队列直接使用堆(heap)来实现,如何删去特定下标元素?不明. 本人喜欢用单调队列存下标 ...
- HDU 3415 Max Sum of Max-K-sub-sequence【单调队列】
<题目链接> 题目大意: 给你一段从1~N的圆形序列,要你求出这段圆形序列中长度不超过K的最大连续子序列之和是多少,并且输出这子序列的起点和终点. 解题分析: 既然是求连续子序列之和,我们 ...
- POJ 2823 Sliding Window (模板题)【单调队列】
<题目链接> <转载于>>> > 题目大意: 给你一段序列和一个长为k的窗口,这个窗口从最左边逐渐向右滑,直到滑到最右边,问你,该窗口在滑动的过程中,最大值和 ...
随机推荐
- BZOJ 1821 部落划分
kruskal.第k-1大的边. 其实prim会更快. #include<iostream> #include<cstdio> #include<cstring> ...
- js屏弊错误
<SCRIPT language=javascript> <!-- window.onerror=function(){return true;} // --> </SC ...
- UVa725 - Division
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; ; int ...
- 【英语】Bingo口语笔记(20) - i长短音
短音有个ei的音,多练习下 长音是咦拉长
- notepad 行替换使用指南
notepad++是开源的文本处理软件,性能堪比ultraedit,不过在转用notepad++之后一直为他的行替换功能纠结,UE当中只需要用 [^p] 就可以表示一行,但是在notepad++当中, ...
- ADB Offline
终极可能原因:版本太旧 http://stackoverflow.com/questions/14993855/android-adb-device-offline-cant-issue-comman ...
- 使用异步任务加载网络上json数据并加载到ListView中
Android中使用网络访问来加载网上的内容,并将其解析出来加载到控件中,是一种很常见的操作.但是Android的UI线程(也就是主线程)中是不允许进行耗时操作的,因为耗时操作会阻塞主线程,影响用户体 ...
- Java魔法类:sun.misc.Unsafe
Unsafe类在jdk 源码的多个类中用到,这个类的提供了一些绕开JVM的更底层功能,基于它的实现可以提高效率.但是,它是一把双刃剑:正如它的名字所预示的那样,它是Unsafe的,它所分配的内存需要手 ...
- Drupal如何处理系统变量?
Drupal的系统变量都保存在数据库variable表中: 然后,开发人员可以通过下面的API函数操作这些系统变量: function variable_get($name, $default = N ...
- WebApp开发经验
1.自适应屏幕 <meta name="viewport" id="viewport" content="width = device-widt ...