#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct student{
int Ge;
int Gi;
int sum;
int sid;
int rank;
int love[6];
}stu[40010];
struct school{
int quota;
int now_quota;
int id[40010];
int last;
}scl[110];
bool cmp(student a,student b){
if(a.sum!=b.sum){
return a.sum>b.sum;
} else{
return a.Ge>b.Ge;
}
}
bool cmpId(int a,int b){
//id数组里存的是排序后数组编号i 真实学生号stu[i]
return stu[a].sid<stu[b].sid;
}
int main() {
int N,M,K;
cin>>N>>M>>K;
for(int i =0;i<M;i++){
cin>>scl[i].quota;
scl[i].now_quota =0;
scl[i].last = -1;
}
for(int i =0;i<N;i++){
stu[i].sid = i;
cin>>stu[i].Ge>>stu[i].Gi;
stu[i].sum = stu[i].Ge+stu[i].Gi;
for(int j =0 ;j<K;j++){
//love[0]是第一志愿
cin>>stu[i].love[j];
}
}
//sort之前数组下标和学生编号相等 按照stu数组的sum属性排序 stu[0]是sum最大的student结构题,他有很多属性包括sid
sort(stu,stu+N,cmp);
//计算每个考生排名
stu[0].rank = 1;
for(int i =1;i<N;i++){
if(i>0&&stu[i].sum==stu[i-1].sum&&stu[i].Ge==stu[i-1].Ge){
stu[i].rank = stu[i-1].rank;
} else{
stu[i].rank = i+1;
}
}
// cout<<stu[1].sid;
//下面对每个生判断其被谁录取
for(int i =0;i<N;i++){
for(int j =0;j<K;j++){
int choice = stu[i].love[j];
int number_quota = scl[choice].quota;
int now_quota = scl[choice].now_quota;
int last = scl[choice].last;
if(now_quota<number_quota||(last!=-1&&stu[last].rank==stu[i].rank)){
//1.还没录够 2.最后一名和他排名相等
//i 是当前stu[i]所在位 必须存i 因为一切操作建立在数组排序之后
scl[choice].id[now_quota]=i;
scl[choice].last =i;
scl[choice].now_quota++;
//id数组从0开始
//选择结束 跳出循环 不需要继续执行了 赶紧下一个学生
break;
}
}
}
// cout<<scl[0].id[1];
//
for(int i =0;i<M;i++){
//下面开始输出
if(scl[i].now_quota>0){
//必须将scl[i].id进行排序 cmpId
sort(scl[i].id,scl[i].id+scl[i].now_quota,cmpId);
for(int j = 0;j<scl[i].now_quota-1;j++){
cout<<stu[scl[i].id[j]].sid<<" ";
}
cout<<stu[scl[i].id[scl[i].now_quota-1]].sid;
cout<<endl;
} else{
cout<<endl;
}
}
return 0;
}
非常难 需要谨慎。