P9214题解
2021sunzishan · · 题解
一道不错的练优先队列的题目。
这篇题解讲得比较细,非常适合新手。
题目大意:
有
思路:
看到“每次都分配到总用时最少的评测节点”这句话,我想都没想,直接用优先队列。
步骤:
-
开一个小根堆。堆中要维护两个元素,一个是节点编号,一个是总用时,所以直接开一个结构体。
-
将
n 个节点全部压入堆,此时总用时为0 。 -
每次读入一个时间
t ,就弹出堆顶元素,将此节点的总用时加上t ,再压回堆中,用一个 vector 来存储每次分配到的编号。 -
最后输出 vector 当中存储的值就可以了。
如果还是不懂,就看代码吧!
切勿抄袭!!!
代码:
#include <bits/stdc++.h>
using namespace std;
inline int read(){//快读
int a=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if (c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
a=a*10+(c-'0');
c=getchar();
}
return f*a;
}
int n,m;
vector<int>a[500005];//记录答案的vector(不能用数组,n*m会爆空间)
struct node{//结构体
long long s;//总用时,别忘了开long long(t<=10^9,m<=10^5,爆int了)
int op;//节点编号
bool operator >(const node &k)const{//重载运算符
if(s!=k.s)return s>k.s;//如果用时不相同,就按用时排
else return op>k.op;//否则按节点编号排
}
};
priority_queue<node,vector<node>,greater<node> >q;//小根堆
//以上为步骤1
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
n=read(),m=read();
for(int i=1;i<=n;i++){//初始化(步骤2)
node k;
k.op=i,k.s=0;
q.push(k);
}
for(int i=1;i<=m;i++){//处理(步骤3)
int t=read();
node k=q.top();//弹出堆顶
q.pop();
k.s+=t;//总用时加上t
q.push(k);//压回堆
a[k.op].push_back(i);//加入答案中
}
for(int i=1;i<=n;i++){//输出答案(步骤4)
for(int j=0;j<a[i].size();j++)
printf("%d ",a[i][j]);
if(a[i].size()==0)printf("0");//如果没有分配到,输出0
printf("\n");
}
return 0;
}
完结~