c++优先队列(堆)
1.最小堆、最大堆
priority_queue<int,vector<int>,greater<int> > f; //最小堆(后面的数逐渐greater)
priority_queue<int,vector<int>,less<int> > f;//最大堆(后面的数逐渐less)
(1).合并果子
https://www.vijos.org/p/1097
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <stdbool.h>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std; priority_queue<int,vector<int>,greater<int> > f; int main()
{
long n,i,a,x,y=;
scanf("%ld",&n);
for (i=;i<=n;i++)
{
scanf("%ld",&a);
f.push(a);
}
for (i=;i<n;i++)
{
x=f.top();
f.pop();
x+=f.top();
f.pop();
f.push(x);
y+=x;
}
printf("%ld",y);
return ;
}
2.自定义
测试:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <stdbool.h>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <iostream>
using namespace std;
#define maxn 100000+5
#define inf 100000+5 long f[maxn],pos[maxn]; //×î´ó¶Ñ
struct cmp1
{
bool operator() (long a,long b)
{
return f[a]<f[b];
}
}; //×îС¶Ñ
struct cmp2
{
bool operator() (long a,long b)
{
return f[a]>f[b];
}
}; //ǰ1/2:a ºó1/2£ºb
priority_queue<int,vector<int>,cmp1 > a;
priority_queue<int,vector<int>,cmp2 > b; int main()
{
long n,d,i;
scanf("%ld",&n);
for (i=;i<=n;i++)
{
scanf("%ld",&f[i]);
// a.push(i);
b.push(i);
}
// while (!a.empty())
while (!b.empty())
{
// printf("%ld ",f[a.top()]);
// a.pop();
printf("%ld ",f[b.top()]);
b.pop();
}
return ;
}
/*
5
2 4 5 1 3
*/
最短路用堆实现,时间复杂度O(nlogn),其实可以用下面的3方法实现,使堆中的数据永远小于等于n个,但是编写比较复杂
两道例题:
http://www.cnblogs.com/cmyg/p/8727643.html
3.对于需要修改、删除堆里的数据,需要自行写堆(优先队列) 参见算法导论
以下是使用优先队列修改、删除堆里的数据,发生错误的案例(代入数据):
//要删除指定值的话只能自己写一个优先队列
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <stdbool.h>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <iostream>
using namespace std;
#define maxn 100000+5
#define inf 100000+5 long f[maxn],pos[maxn]; //最大堆
struct cmp1
{
bool operator() (long a,long b)
{
return f[a]<f[b];
}
}; //最小堆
struct cmp2
{
bool operator() (long a,long b)
{
return f[a]>f[b];
}
}; //从小到大排序
//前(n+1)/2个数:a(最大堆)
//后n/2个数:b(最小堆)
//中位数永远是a的最大值
//增添和删除:也许需要a的最大值移向b或b的最小值移向a
priority_queue<int,vector<int>,cmp1 > a;
priority_queue<int,vector<int>,cmp2 > b; void change()
{
long d;
if (a.size()<b.size())
{
d=b.top();
b.pop();
a.push(d);
pos[d]=;
}
else if (a.size()>b.size()+)
{
d=a.top();
a.pop();
b.push(d);
pos[d]=;
}
} int main()
{
long n,g;
char s[];
scanf("%ld",&n);
while (n)
{
n--;
scanf("%s",s);
if (strcmp(s,"Pop")==)
{
if (g==)
{
printf("Invalid\n");
continue;
}
printf("%ld\n",f[g]);
if (pos[g]==)
{
f[g]+=inf; printf("--%ld\n",a.top()); a.pop(); printf("--%ld\n",a.top());
//这里错了
}
else
{
f[g]-=inf;
b.pop();
}
g--;
change();
}
else if (strcmp(s,"Push")==)
{
g++;
scanf("%ld",&f[g]);
if (a.empty() || f[g]<=f[a.top()])
{
a.push(g);
pos[g]=;
}
else
{
b.push(g);
pos[g]=;
}
change();
}
else
{
if (g==)
printf("Invalid\n");
else
printf("%ld\n",f[a.top()]);
}
}
return ;
}
/*
100
Push 1
PeekMedian
Push 2
PeekMedian
Push 3
PeekMedian
Push 4
PeekMedian
Push 5
PeekMedian
Pop
PeekMedian
Pop
PeekMedian
Pop
PeekMedian
Pop
PeekMedian
Pop
PeekMedian
Pop 100
Push 5
PeekMedian
Push 4
PeekMedian
Push 3
PeekMedian
Push 2
PeekMedian
Push 1
PeekMedian
Pop
PeekMedian
Pop
PeekMedian
Pop
PeekMedian
Pop
PeekMedian
Pop
PeekMedian
Pop */
3.1 求第k大,k的值每次最多变化为1
求中位数
https://www.patest.cn/contests/gplt/L3-002
Solution:
分成两个堆,
对数从小到大排序
前(n+1)/2个数:a(最大堆)
后n/2个数:b(最小堆)
中位数永远是a的最大值
增添和删除:也许需要a的最大值移向b或b的最小值移向a
注意pos和input数组,这个是用于定位的,从而可以修改数据,删除数据
//还可以求第k大(k值固定) //要删除指定值的话只能自己写一个优先队列
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <stdbool.h>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <iostream>
using namespace std;
#define maxn 100000+5
#define inf 100000+5 struct node
{
long d,g;
}; long f[maxn],treenum[maxn];
//posa[i],posb[i]:a/b中第i个点在输入中的位置
//input[i]:输入中第i个点在树的位置(pos标记是在哪棵树)
long a[maxn],b[maxn],posa[maxn],posb[maxn],input[maxn]; //最大堆
struct cmp1
{
bool operator() (long a,long b)
{
return f[a]<f[b];
}
}; //最小堆
struct cmp2
{
bool operator() (long a,long b)
{
return f[a]>f[b];
}
}; //从小到大排序
//前(n+1)/2个数:a(最大堆)
//后n/2个数:b(最小堆)
//中位数永远是a的最大值
//增添和删除:也许需要a的最大值移向b或b的最小值移向a
//priority_queue<int,vector<int>,cmp1 > a;
//priority_queue<int,vector<int>,cmp2 > b; void up_min(long t[],long pos[],long input[],long i)
{
long j,temp;
while (i>)
{
j=i>>;
//j<i
if (t[j]>t[i])
{
temp=t[i];
t[i]=t[j];
t[j]=temp; temp=pos[i];
pos[i]=pos[j];
pos[j]=temp; input[pos[i]]=i;
input[pos[j]]=j;
}
else
break;
i=j;
}
} void down_min(long t[],long pos[],long input[],long i)
{
long j,temp;
while (( i<<)<=t[])
{
j=i<<;
if (j!=t[] && t[j+]<t[j])
j=j|;
//i<j
if (t[i]>t[j])
{
temp=t[i];
t[i]=t[j];
t[j]=temp; temp=pos[i];
pos[i]=pos[j];
pos[j]=temp; input[pos[i]]=i;
input[pos[j]]=j;
}
else
break;
i=j;
}
} void push_min(long t[],long pos[],long input[],struct node p)
{
t[]++;
t[t[]]=p.d;
pos[t[]]=p.g;
input[p.g]=t[];
up_min(t,pos,input,t[]);
} void pop_min(long t[],long pos[],long input[])
{
t[]=t[t[]];
pos[]=pos[t[]];
input[pos[]]=;
t[]--;
down_min(t,pos,input,);
} void minus_min(long t[],long pos[],long input[],long w,long d)
{
t[w]-=d;
up_min(t,pos,input,w);
} void plus_min(long t[],long pos[],long input[],long w,long d)
{
t[w]+=d;
down_min(t,pos,input,w);
} void up_max(long t[],long pos[],long input[],long i)
{
long j,temp;
while (i>)
{
j=i>>;
//j<i
if (t[j]<t[i])
{
temp=t[i];
t[i]=t[j];
t[j]=temp; temp=pos[i];
pos[i]=pos[j];
pos[j]=temp; input[pos[i]]=i;
input[pos[j]]=j;
}
else
break;
i=j;
}
} void down_max(long t[],long pos[],long input[],long i)
{
long j,temp;
while ((i<<)<=t[])
{
j=i<<;
if (j!=t[] && t[j+]>t[j])
j=j|;
//i<j
if (t[i]<t[j])
{
temp=t[i];
t[i]=t[j];
t[j]=temp; temp=pos[i];
pos[i]=pos[j];
pos[j]=temp; input[pos[i]]=i;
input[pos[j]]=j;
}
else
break;
i=j;
}
} void push_max(long t[],long pos[],long input[],struct node p)
{
long i,j,temp;
t[]++;
t[t[]]=p.d;
pos[t[]]=p.g;
input[p.g]=t[];
up_max(t,pos,input,t[]);
} void pop_max(long t[],long pos[],long input[])
{
t[]=t[t[]];
pos[]=pos[t[]];
input[pos[]]=;
t[]--;
down_max(t,pos,input,);
} void plus_max(long t[],long pos[],long input[],long w,long d)
{
t[w]+=d;
up_max(t,pos,input,w);
} void minus_max(long t[],long pos[],long input[],long w,long d)
{
t[w]-=d;
down_max(t,pos,input,w);
} long size(long t[])
{
return t[];
} struct node top(long t[],long pos[])
{
struct node p;
p.d=t[];
p.g=pos[];
return p;
} bool empty(long t[])
{
if (t[]==)
return true;
else
return false;
} void change()
{
struct node cond;
long d;
if (size(a)<size(b))
// if (a.size()<b.size())
{
cond=top(b,posb);
pop_min(b,posb,input);
push_max(a,posa,input,cond);
// d=b.top();
// b.pop();
// a.push(d);
treenum[cond.g]=;
}
else if (size(a)>size(b)+)
// else if (a.size()>b.size()+1)
{
cond=top(a,posa);
pop_max(a,posa,input);
push_min(b,posb,input,cond);
// d=a.top();
// a.pop();
// b.push(d);
treenum[cond.g]=;
}
} int main()
{
struct node cond;
long n,g;
char s[];
a[]=; b[]=;
scanf("%ld",&n);
while (n)
{
n--;
scanf("%s",s);
if (strcmp(s,"Pop")==)
{
if (g==)
{
printf("Invalid\n");
continue;
}
printf("%ld\n",f[g]);
if (treenum[g]==)
{
// f[g]+=inf;
// a.pop();
plus_max(a,posa,input,input[g],inf);
pop_max(a,posa,input);
}
else
{
// f[g]-=inf;
// b.pop();
minus_min(b,posb,input,input[g],inf);
pop_min(b,posb,input);
}
g--;
change();
}
else if (strcmp(s,"Push")==)
{
g++;
scanf("%ld",&f[g]);
// if (a.empty() || f[g]<=f[a.top()])
if (empty(a) || f[g]<=top(a,posa).d)
{
cond.d=f[g];
cond.g=g;
// a.push(g);
push_max(a,posa,input,cond);
treenum[g]=;
}
else
{
cond.d=f[g];
cond.g=g;
// b.push(g);
push_min(b,posb,input,cond);
treenum[g]=;
}
change();
}
else
{
if (g==)
printf("Invalid\n");
else
// printf("%ld\n",f[a.top()]);
printf("%ld\n",top(a,posa).d);
}
}
return ;
}
/*
100
Push 1
PeekMedian
Push 2
PeekMedian
Push 3
PeekMedian
Push 4
PeekMedian
Push 5
PeekMedian
Pop
PeekMedian
Pop
PeekMedian
Pop
PeekMedian
Pop
PeekMedian
Pop
PeekMedian
Pop 100
Push 5
PeekMedian
Push 4
PeekMedian
Push 3
PeekMedian
Push 2
PeekMedian
Push 1
PeekMedian
Pop
PeekMedian
Pop
PeekMedian
Pop
PeekMedian
Pop
PeekMedian
Pop
PeekMedian
Pop */
3.2 求第k大的数(k永远不变)
前k大的数放入最小堆a,其它的数放入最大堆b
添加数据:数据放入堆a,若堆a的大小大于k,则取最小的数放入堆b
修改数据:修改后根据情况是否把一个数从a移至b或从b移至a
c++优先队列(堆)的更多相关文章
- Java学习笔记--PriorityQueue(优先队列)(堆)
PriorityQueue(优先队列)实际上是一个堆(不指定Comparator时默认为最小堆)队列既可以根据元素的自然顺序来排序,也可以根据 Comparator来设置排序规则.队列的头是按指定排序 ...
- Expedition---poj2431(优先队列-堆的实现)
题目链接:http://poj.org/problem?id=2431 题意:一辆卡车需要行驶 L 距离,车上油的含量为 P,在行驶的过程中有 n 个加油站 每个加油站到终点的距离是ai,每个加油站最 ...
- 剑指 Offer 40. 最小的k个数 + 优先队列 + 堆 + 快速排序
剑指 Offer 40. 最小的k个数 Offer_40 题目描述 解法一:排序后取前k个数 /** * 题目描述:输入整数数组 arr ,找出其中最小的 k 个数.例如,输入4.5.1.6.2.7. ...
- dij最短路优先队列堆的时候,加边
不能用全局数组d[u]>d[rhs.u]. 这样后面会修改d[u]值然而本来里面的点顺序不该修改,却被修改了. 应该用栈还存进去的临时变量,比如d>rhs.d. 优先队列重载小于号'< ...
- Dijkstra+优先队列 堆优化
关于堆优化 传统\(Dijkstra\),在选取中转站时,是遍历取当前最小距离节点,但是我们其实可以利用小根堆(STL的priority_queue)优化这个过程,从而大大降低复杂(\(O(V2+E) ...
- CJOJ 2484 函数最小值 / Luogu 2085 函数最小值(STL优先队列,堆)
CJOJ 2484 函数最小值 / Luogu 2085 函数最小值(STL优先队列,堆) Description 有n个函数,分别为F1,F2,...,Fn.定义 \(Fi(x)=Aix^2+Bix ...
- 浅谈堆-Heap(一)
应用场景和前置知识复习 堆排序 排序我们都很熟悉,如冒泡排序.选择排序.希尔排序.归并排序.快速排序等,其实堆也可以用来排序,严格来说这里所说的堆是一种数据结构,排序只是它的应用场景之一 Top N的 ...
- 算法导论 第六章 2 优先队列(python)
优先队列: 物理结构: 顺序表(典型的是数组){python用到list} 逻辑结构:似完全二叉树 使用的特点是:动态的排序..排序的元素会增加,减少#和快速排序对比 快速一次排完 增 ...
- [BZOJ 2006] [NOI 2010]超级钢琴(贪心+ST表+堆)
[BZOJ 2006] [NOI 2010]超级钢琴(贪心+ST表+堆) 题面 给出一个长度为n的序列,选k段长度在L到R之间的区间,一个区间的值等于区间内所有元素之的和,使得k个区间的值之和最大.区 ...
随机推荐
- Shader做剪影效果
某渣渣甩了一个需求给我,并且说我不会写.我明知是激将法,但是想想这需求也太简单了,我好像也不怎么会QAQ.为了表示我对shader的热爱,写就写. 需求是这样的: 这是一个漂亮的MM,但是渣渣不想让人 ...
- [!] Attempt to read non existent folder `***********`
以前遇到过的问题,最近又出现了,问题单独列出,容易查找: $ pod install [!] Attempt to read non existent folder `/Users/galahad/D ...
- Thunder团队--Beta发布用户使用报告
Thunder爱阅app Beta 发布用户使用报告 用户数量:14人 以下为用户评论:(注:为了保护用户的姓名权,以下用户名以昵称形式给出.) 序号 昵称 个人信息 获得软件途径 使用次数 用户评论 ...
- 实验三— —敏捷开发与XP实践
---恢复内容开始--- java的第二个实验——JAVA面向对象程序设计 北京电子科技学院 实 验 报 告 课程:Java程序设计 班级:1352 姓名:林涵锦 学号:2013 ...
- web10 动态action的应用
电影网站:www.aikan66.com 项目网站:www.aikan66.com游戏网站:www.aikan66.com图片网站:www.aikan66.com书籍网站:www.aikan66.co ...
- 除了C语言,C++······竟然还有Z语言?
只能说自己见识短,头一次听说Z语言.先普及一下吧: Z语言是由牛津大学程序设计研究小组开发的一种形式语言,它是一种以一阶谓词演算为主要理论基础的规约语言,是一种功能性语言.Z语言是将事物的状态和行为用 ...
- 使用 java 实现一个简单的 markdown 语法解析器
1. 什么是 markdown Markdown 是一种轻量级的「标记语言」,它的优点很多,目前也被越来越多的写作爱好者,撰稿者广泛使用.看到这里请不要被「标记」.「语言」所迷惑,Markdown 的 ...
- 旧文备份:CANopen中SYNC的功能和使用
SYNC是CANopen管理各节点同步数据收发的一种方法,相当于网络节拍,基于同步的PDO按照这个网络节拍来执行实时数据的收发.SYNC属于生产/消费型通讯方式,网络中有且只有一个SYNC生产者,一般 ...
- Apache优化之多路处理模块理解
前言: 当项目被多人访问时导致访问数度变慢,查了许多资料,了解到Apache的核心模块——MPM(多路处理访问模块).在此对MPM的一些知识点进行整理. MPM_WINNT模块 windows系统使用 ...
- [cnBeta]阿里云推出全栈IPv6解决方案 加速推进下一代互联网应用
https://www.cnbeta.com/articles/tech/795695.htm 访问: 阿里云 - 最高1888元通用代金券立即可用 作为国内首个全面支持IPv6的云厂商,过去5个月, ...