大一寒假集训(9)—优先队列
知识点
定义一个priority_queue的方法为: priority_queue name;
//type通常为结构体
其中,type可以是任何基本类型或者容器,name为优先队 列的名字。 和queue不一样的是,priority_queue没有front()和back(), 而只能通过top()或pop()访问队首元素(也称堆顶元素),也 就是优先级最高的元素。
typedef long long LL;
struct sa {LL x; LL y; LL sum; };
LL a[400005],b[400005];
bool operator < (const sa &a,const sa &b)
{
return a.sum >b.sum;
//表示的是从小到大
}
Priority_queue队列
大根堆:从大到小排列。 小根堆:从小到大排列。 优先队列就是堆,也可以自己手写堆。 //小根堆的写法 priority_queue<int,vector,greater > vis; //大根堆的写法 priority_queue<int,vector,less > vis;
当就是1个类型,可以这样直接写; 也可以用结构题。
1.合并果子-优先队列 nefu 1688
本题是典型的使用优先队列的题
#include <bits/stdc++.h>
using namespace std;
int n;
int x,ans;
int y2;
priority_queue<int,vector<int>,greater<int> >q;
int main()
{
ans=0;
cin>>n;
for (int i=0;i<n;i++)
{
cin>>x;
q.push(x);
}
while (q.size()>1)
{
int y1=q.top();
q.pop();
y2=q.top();
q.pop();
q.push(y1+y2);
ans+=y1+y2;
}
cout<<ans;
return 0;
}
2.合成陨石-优先队列 nefu 355
本题与第一题不同的是多组输入,记得初始化即可
#include <bits/stdc++.h>
using namespace std;
int n;
int x,ans;
priority_queue<int,vector<int>,greater<int> >q;
int main()
{
while (cin>>n)
{
for (int i=0;i<n;i++)
{
cin>>x;
q.push(x);
}
ans=0;//记得初始化
while (q.size()>1)
{
int y1=q.top();
q.pop();
int y2=q.top();
q.pop();
q.push(y1+y2);
ans+=y1+y2;
}
cout<<ans<<endl;
q.pop();//初始化
}
return 0;
}
3.买饭-优先队列 nefu 1537
本题注意结构体自定义比较的方法
#include <bits/stdc++.h>
using namespace std;
int n;
int t;
double ans1,ans2;
struct que
{
int t;//时间
int num;//名字
};
bool operator < (const que &s1,const que &s2)
{
if (s1.t!=s2.t)
return s1.t>s2.t;
else
return s1.num>s2.num;
}
priority_queue<que,vector<que> >q;
int main()
{
ios::sync_with_stdio(false);
cin>>n;
ans1=0;
ans2=0;
for (int i=1;i<=n;i++)
{
cin>>t;
q.push({t,i});
}
while (!q.empty())
{
que r=q.top();
q.pop();
ans1+=ans2;//总时间
ans2+=r.t*1.0;//当前人的等待时间
if (q.size()==0)
cout<<r.num<<endl;
else
cout<<r.num<<" ";
}
printf("%.2lf\n",ans1/(1.0*n));
return 0;
}
4.堆-优先队列 nefu 1692
基本操作,很简单的题
#include <bits/stdc++.h>
using namespace std;
priority_queue<int,vector<int>,greater<int> >q;
int n;//n次操作
int main()
{
ios::sync_with_stdio(false);//注意添加这一坨,不然会tle
cin>>n;
int x;//操作1 2 3
int y;//输入的数
for (int i=1;i<=n;i++)
{
cin>>x;
if (x==1)
{
cin>>y;
q.push(y);
}
if (x==2)
cout<<q.top()<<endl;
if(x==3)
q.pop();
}
return 0;
}
5.瑞瑞的木板-优先队列 nefu 1691
与第一题类似
#include <bits/stdc++.h>
using namespace std;
priority_queue<int,vector<int>,greater<int> >q;
int n;//木板数量
int x;
long long ans1;
int main()
{
cin>>n;
ans1=0;
for (int i=1;i<=n;i++)
{
cin>>x;
q.push(x);
}
while (q.size()>1)
{
int y1=q.top();
q.pop();
int y2=q.top();
q.pop();
q.push(y1+y2);
ans1+=y1+y2;
}
cout<<ans1;
return 0;
}
6.序列合并-优先队列 nefu 1689
详细题解如下
本题我应该一开始就听题目用scanf ,我用cin就一直tle
#include <bits/stdc++.h>
using namespace std;
int n,a[400005],b[400005];
struct lay
{
int x;
int y;
long long ans;
};
bool operator < (const lay &s1,const lay &s2)
{
return s1.ans>s2.ans;
}
priority_queue<lay,vector<lay> >q;
int main()
{
//ios::sync_with_stdio(false);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&b[i]);
for (int i=1;i<=n;i++)
q.push({i,1,a[i]+b[1]});
for (int i=1;i<=n;i++)
{
lay tmp=q.top();
q.pop();
printf("%lld\n",tmp.ans);
int x0=tmp.x;
int y0=tmp.y;
q.push({x0,y0+1,a[x0]+b[y0+1]});
}
return 0;
}
7.桐桐的新闻系统-优先队列 nefu 1690
#include <bits/stdc++.h>
using namespace std;
char ch[10];
int id,t,k;
//int r1,r2;
struct lay
{
int id;//名
int t;//时间
int ans;//总时间
};
bool operator < (const lay &s1,const lay &s2)
{
if (s1.ans!=s2.ans)
return s1.ans>s2.ans;
else return s1.id>s2.id;
}
priority_queue<lay,vector<lay> >q;
int main()
{
ios::sync_with_stdio(false);
while (cin>>ch&&ch[0]!='#')
{
cin>>id>>t;
q.push({id,t,t});
}
cin>>k;//执行k次指令
for (int i=1; i<=k; i++)
{
lay tmp=q.top();
q.pop();
cout<<tmp.id<<endl;
q.push({tmp.id,tmp.t,tmp.ans+tmp.t});
}
return 0;
}