优先队列的定义:优先级高的在前面,优先级低的在后面,每次操作后会自动调整!
1.priority_queue<int,vector,less >q;//从大到小
2.priority_queue<int,vector,greater >q;//从小到大
3.priority_queue < node > q;
struct node
{
int x,y;
long long sum;
};
bool operator < (const node &s1,const node &s2)
{
return s1.sum>s2.sum;//是从小到大排列的
}
优先队列常见操作:
1.q.pop();
2.q.top();
3.q.push(x);
优先队列题目:
1.http://acm.nefu.edu.cn/problemShow.php?problem_id=1537
在这里插入代码片优先队列中放结构体,自定义比较结构体需要重载运算符,功能和sort中的自定义比较函数cmp一样。
要定义两个变量time和ans,time用来表示当前的人的等待时间,ans用来记录总的等待时间!!!
#include <bits/stdc++.h>
using namespace std;
int n,x;
struct node
{
int x,num;
};
bool operator < (const node &s1,const node &s2)//结构体自定义比较,重载运算符
{
if(s1.x!=s2.x)return s1.x>s2.x;
return s1.num>s2.num;
}
priority_queue<node,vector<node> >q;
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x;
q.push({x,i});
}
double tim=0,ans=0;
while(!q.empty())
{
node tmp=q.top();q.pop();
ans+=tim;//tim记录当前人的等待时间,ans记录等待时间总和
tim+=1.0*tmp.x;
q.empty()?printf("%d\n",tmp.num):printf("%d ",tmp.num);
}
printf("%.2lf\n",ans/(1.0*n));
return 0;
}
2.n块合成n-1块https://www.luogu.com.cn/problem/P1334
#include <bits/stdc++.h>
using namespace std;
int n,x;
long long ans;
priority_queue<int,vector<int>,greater<int> >q;//队列中元素按从小到大排序
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x;
q.push(x);
}
while(q.size()>1)
{
int t1=q.top();q.pop();
int t2=q.top();q.pop();
q.push(t1+t2);
ans+=t1+t2;
}
printf("%lld\n",ans);
return 0;
}
3.队列的合并https://www.luogu.com.cn/problem/P1631
利用坐标实现队列的合并
首先,把A和B两个序列分别从小到大排序,变成两个有序队列。这样,从A和B中各任取一个数相加得到N2个和,可以把这些和看成形成了n个有序表/队列:
A[1]+B[1] <= A[1]+B[2] <= … <= A[1]+B[N]
A[2]+B[1] <= A[2]+B[2] <= … <= A[2]+B[N]
……
A[N]+B[1] <= A[N]+B[2] <= … <= A[N]+B[N]
接下来,就相当于要将这N个有序队列进行合并排序:
首先,将这N个队列中的第一个元素放入一个优先队列中;
然后,每次取出堆中的最小值。若这个最小值来自于第k个队列,那么,就将第k个队列的下一个元素放入堆中。
时间复杂度:O(NlogN)。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+10;
int n,a[N],b[N];
struct node
{
int x,y;
ll sum;
};
bool operator < (const node &s1,const node &s2)
{return s1.sum>s2.sum;}
priority_queue<node,vector<node> >q;
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
cin>>b[i];
for(int i=1;i<=n;i++)
q.push({i,1,a[i]+b[1]});
for(int i=1;i<=n;i++)
{
node tmp=q.top();q.pop();
i==n?printf("%lld\n",tmp.sum):printf("%lld ",tmp.sum);
int x=tmp.x,y=tmp.y;
q.push({x,y+1,a[x]+b[y+1]});
}
return 0;
}
4.队列的合并http://acm.nefu.edu.cn/problemShow.php?problem_id=1690
#include <bits/stdc++.h>
using namespace std;
char s[10];
int k,id,tim;
struct node
{
int id,tim,sum;//基础时间为tim,sum为tim的倍数(每次增加tim)
};
bool operator < (const node &s1,const node &s2)
{
if(s1.sum!=s2.sum)return s1.sum>s2.sum;
return s1.id>s2.id;
}
priority_queue<node,vector<node> >q;
int main()
{
ios::sync_with_stdio(false);
while(cin>>s&&s[0]!='#')
{
cin>>id>>tim;
q.push({id,tim,tim});
}
cin>>k;
while(k--)
{
node tmp=q.top();q.pop();
printf("%d\n",tmp.id);
q.push({tmp.id,tmp.tim,tmp.sum+tmp.tim});//把该id对应的时间sum加上tim
}
return 0;
}