Summary
我太菜了,E 题没加 endl 就交上去了,真想找块豆腐撞死 >﹏<
整体来说有一些重复的题,只要读懂题就不难了
观察代码大小也看出来有3个重复题了
Information
No. | Title | AC/Submit |
---|---|---|
A | 买饭-优先队列 | 54/114 |
B | 合并果子-优先队列 | 57/104 |
C | 序列合并-优先队列 | 23/61 |
D | 合成陨石-优先队列 | 48/109 |
E | 堆-优先队列 | 45/55 |
F | 瑞瑞的木板-优先队列 | 40/107 |
G | 桐桐的新闻系统-优先队列 | 27/36 |
Problem B: 合并果子-优先队列 (1688) [57/104]
Problem D: 合成陨石-优先队列 (355) [48/109]
Problem F: 瑞瑞的木板-优先队列 (1691) [40/107]
Tips
这三个题是一毛一样的,代码也是通用的
B 和 D 就不用说了,样例都是一样的
这个 F 是要把大木板切成小木板,反过来就是把小木板合成大木板
注意要定义成小顶堆,不要默认的大顶堆 <(^-^)>
Code
三题通用代码 ,嘿嘿 ~
#include <bits/stdc++.h>
using namespace std;
int main()
{
priority_queue<long long,vector<long long>,greater<long long> >q;
long long tmp,n,sum;
while(cin>>n)
{
sum=0;
while(!q.empty())q.pop();
while(n--)
{
cin>>tmp;
q.push(tmp);
}
while(q.size()!=1)
{
tmp=q.top();
q.pop();
tmp+=q.top();
q.pop();
sum+=tmp;
q.push(tmp);
}
cout<<sum<<endl;
}
return 0;
}
Problem A: 买饭-优先队列 (1537) [54/114]
Tips
买饭这个看着就眼熟,我记得这个东西叫接水来着
果然 Input 就暴露了它的真实身份,嗯 ~ o( ̄▽ ̄)o
第2行分别表示每人的接水时间
似乎不用优先队列,贪心方法手动排序一下就行了。
Code
#include <bits/stdc++.h>
using namespace std;
struct People
{
int t;
int n;
}p[1001];
int cmp(People p1,People p2)
{
if(p1.t!=p2.t)return p1.t<p2.t;
return p1.n<p2.n;
}
int main()
{
int n;
double sum=0;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>p[i].t;
p[i].n=i+1;
}
sort(p,p+n,cmp);
for(int i=0;i<n-1;i++)
{
cout<<p[i].n<<" ";
sum+=(n-i-1)*p[i].t;
}
cout<<p[n-1].n<<endl;
printf("%.2f",sum/n);
return 0;
}
Problem C: 序列合并-优先队列 (1689) [23/61]
Tips
这个有点复杂,不过有大佬 jwMM 讲解
简单分析一下,用样例举例(非代码,不可运行)
a[] = 2 6 6
b[] = 1 4 8
用 a 中第 i 个分别加上 b 中元素,得到以下结果
3 6 8
7 10 14
7 10 14
由于给定数据是升序的,因此 同一行左侧数据一定大于等于右侧数据
即 3 ≥ 6 ≥ 8
,7 ≥ 10 ≥ 14
那么只需要先将第一列入优先队列,然后依次向后查找
每次取最小元素输出并将最小元素右侧元素加入队列
Code
#include <bits/stdc++.h>
using namespace std;
struct point
{
int x,y;
long long sum;
}p;
long long a[400000],b[400000];
bool operator < (const point &p1,const point &p2)
{
return p1.sum>p2.sum;
}
int main()
{
priority_queue<point>q;
int n,ans=0;
scanf("%d",&n);
for(int i=0;i<n;i++)scanf("%lld",&a[i]);
for(int i=0;i<n;i++)scanf("%lld",&b[i]);
for(int i=0;i<n;i++)
{
p.x=0;
p.y=i;
p.sum=a[0]+b[i];
q.push(p);
}
while(!q.empty())
{
p=q.top();
q.pop();
printf("%lld\n",p.sum);
if(++ans==n)break;
p.x++;
p.sum=a[p.x]+b[p.y];
q.push(p);
}
return 0;
}
Problem E: 堆-优先队列 (1692) [45/55]
Tips
简单的模板 (shui) 题,练习队列的基本使用方法。
Code
#include <bits/stdc++.h>
using namespace std;
int main()
{
priority_queue<long long,vector<long long>,greater<long long> >q;
long long tmp,n,sum;
while(cin>>n)
{
while(n--)
{
cin>>tmp;
switch(tmp)
{
case 1:
cin>>tmp;
q.push(tmp);
break;
case 2:
cout<<q.top()<<endl;
break;
case 3:
q.pop();
}
}
}
return 0;
}
Problem G: 桐桐的新闻系统-优先队列 (1690) [27/36]
Tips
可以分别记录每个人的 qnum ,消息的 period 和下次收消息的时间
每次根据时间判断接收消息的人并输出序号,同时对应消息回队列中等待
Code
#include <bits/stdc++.h>
using namespace std;
struct People
{
int qnum;
int period;
long long time;
}p;
bool operator < (const People &p1,const People &p2)
{
if(p1.time!=p2.time)return p1.time>p2.time;
return p1.qnum>p2.qnum;
}
int main()
{
priority_queue<People>q;
string cmd;
int n;
while(cin>>cmd)
{
if(cmd=="#")break;
cin>>p.qnum>>p.period;
p.time=p.period;
q.push(p);
}
cin>>n;
while(n--)
{
p=q.top();
cout<<p.qnum<<endl;
p.time+=p.period;
q.pop();
q.push(p);
}
return 0;
}