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个区间的值之和最大.区 ...
随机推荐
- 关于go语言中的WaitGroup
如果你刚接触Go语言并且想用它构建高并发,高性能的应用,弄明白WaitGroups是怎么回事很重要. 在本教程中,我们将掌握以下内容: WaitGroups的用途 一个WaitGroups的简单示例 ...
- 微软职位内部推荐-Software Engineer II-Senior Software Engineer for Satori
微软近期Open的职位: Title: Software Engineer II-Senior Software Engineer for Satori, STC Location: Beijing ...
- mv命令详解
基础命令学习目录首页 原文链接:https://www.cnblogs.com/piaozhe116/p/6084214.html mv命令是move的缩写,可以用来移动文件或者将文件改名(move ...
- ./configure的含义
在实践安装nginx的时候,不知道./configure是什么意思,这里特地记录一下. 在linux中./代表当前目录,属于相对路径../代表上一级目录,属于相对路径/代表根目录,/开头的文件都是绝对 ...
- 感谢Thunder
感谢Thunder团队中的每一位成员. 组长王航认真负责,是一个合格优秀的领导者与伙伴,老师布置的任务都会及时分配给每个人,对待每一项任务都认真严谨负责,了解每个成员的优势及强项. 成员李传康.宋雨. ...
- 第39次Scrum会议(12/5)【欢迎来怼】
一.小组信息 队名:欢迎来怼小组成员队长:田继平成员:李圆圆,葛美义,王伟东,姜珊,邵朔,阚博文 小组照片 二.开会信息 时间:2017/12/5 11:35~11:57,总计22min.地点:东北师 ...
- 20135316王剑桥 linux第三周课实验笔记
通过使用标准的字符码能够对文档中的字母和符号进行编码. 三种重要的数字表现形式: 1. 无符号数:编码基于传统的二进制表示法表示大于或等于零的数字. 2. 补码:编码是表示有符号整数的最常见方法,可以 ...
- FileInputStream 读取文件数据的输入字节流
package com.inputstream; /* File类: 用于描述一个文件或者文件夹的. 通过File对象我们可以读取文件或者文件夹的属性数据,如果我们需要读取文件的内容数据,那么我们需要 ...
- Alpha版本冲刺(一)
目录 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:凯琳 组员6:丹丹 组员7:家伟 组员8:政演 组员9:黄鸿杰 组员10:刘一好 组员11:何宇恒 展示组内 ...
- poi读取Excel文件和图片
首先得说一下,Excel文件是有03版和07版的区别的,也就是.xls和.xlsx,这两个文件需要分开读取. 其它的废话就不说了,直接贴代码: package util; import java.io ...