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;
}