题解:P16441 [XJTUPC 2026] 直播获奖
Jason20090916 · · 题解
模拟,理清思路即可。
按 UID 升序排序,逐个将其加入全集并模拟选拔。
在选拔阶段,先选出 A 队,因为 B 队关于工会的判断条件要用到 A 队。
首先目前所有人按照成绩降序排序。
当枚举到一个人
- A 队人数小于
5 人。 - A 队中与
S_i 的元素相同的人数小于4 人。
当所有人都被枚举过是否能进入 A 队,将 A 队的人从全集中除去。之后枚举
- B 队人数小于
12 人。 - B 队中与
S_i 的工会相同的人数小于5 人。
注意输出 A,B 队时要按照 UID 升序排序,选拔一次后恢复全集。 ::::success[Code]
#include<bits/stdc++.h>
using namespace std;
constexpr int MAXN = 109;
int n;
struct Node {
bool flag;
int id, uid, score;
} a[MAXN];
bool cmp1(Node x, Node y) {
return x.uid < y.uid;
}
bool cmp2(Node x, Node y) {
return x.score > y.score;
}
vector<int> A, B;
vector<Node> ve;
map<int, int> mp;
int cnt[2];
bool chka(Node x) {
if(A.size() >= 5) return 0;
if(cnt[x.flag] >= 4) return 0;
return 1;
}
bool chkb(Node x) {
if(B.size() >= 12) return 0;
if(mp[x.id] >= 5) return 0;
return 1;
}
int main(){
cin >> n;
for(int i = 1; i <= n; i++) a[i].uid = i, cin >> a[i].flag >> a[i].id >> a[i].score;
sort(a + 1, a + 1 + n, cmp1);
for(int i = 1; i <= n; i++) {
ve.clear();
for(int j = 1; j <= i; j++) ve.push_back(a[j]);
sort(ve.begin(), ve.end(), cmp2);
A.clear(), B.clear(), mp.clear();
cnt[0] = cnt[1] = 0;
if(ve.size() <= 4) for(auto it : ve) A.push_back(it.uid);
else {
for(auto i = ve.begin(); i != ve.end();) {
auto it = *i;
if(chka(it)) {
A.push_back(it.uid);
cnt[it.flag]++;
mp[it.id]++;
i = ve.erase(i);
}
else i++;
}
for(auto it : ve) {
if(chkb(it)) {
B.push_back(it.uid);
mp[it.id]++;
}
}
}
sort(A.begin(), A.end());
sort(B.begin(), B.end());
for(auto it : A) cout << it << ' ';
for(auto it : B) cout << it << ' ';
cout << '\n';
}
return 0;
}
::::