题解:AtCoder AT_awc0129_a Addressing Wedding Invitations
【题目来源】
AtCoder:A - Addressing Wedding Invitations
【题目描述】
Takahashi, as an organizing staff member of an international conference, has been tasked with preparing invitation letters for the participants.
The invitation list contains \(N\) participants. The \(i\)-th participant \((1 \leq i \leq N)\) has a name \(S_i\) and a title \(R_i\) registered. On the invitation, each participant's name is followed by an honorific determined by the following rules, separated by a space:
- For people whose title is
teacherordoctor, the honorificsenseiis appended. - For people whose title is
studentorother, the honorificsanis appended.
Furthermore, co-organizer Aoki has requested that "the order of the list be adjusted." Specifically, the participants are divided into the following two groups, and all members of Group A are placed before all members of Group B:
- Group A: People whose title is
teacherordoctor - Group B: People whose title is
studentorother
Within each group, the order given in the input (ascending order of \(i\)) is preserved. That is, the relative order of participants belonging to the same group must match their relative order in the input.
For the rearranged list, output each participant's name and honorific separated by a space, in order. Note that the honorific to output is not the title itself, but sensei or san as determined by the rules above.
高橋作为一场国际会议的组织工作人员,负责为参会者准备邀请函。
邀请名单中有 \(N\) 位参会者。第 \(i\) 位参会者 \((1 \leq i \leq N)\) 注册了姓名 \(S_i\) 和头衔 \(R_i\)。在邀请函上,每位参会者的姓名后面会根据以下规则加上一个敬称,中间用空格分隔:
- 头衔为
teacher或doctor的人,后面加上敬称sensei。 - 头衔为
student或other的人,后面加上敬称san。
此外,共同组织者青木要求"调整名单的顺序"。具体地,将参会者分为以下两组,A 组的所有成员排在 B 组的所有成员之前:
- A 组:头衔为
teacher或doctor的人 - B 组:头衔为
student或other的人
每组内部保持输入中的顺序(即按 \(i\) 的升序)。也就是说,属于同一组的参会者之间的相对顺序必须与输入中的相对顺序一致。
对于重新排列后的名单,按顺序输出每位参会者的姓名和敬称,中间用空格分隔。注意,输出的敬称不是头衔本身,而是根据上述规则确定的 sensei 或 san。
【输入】
\(N\)
\(S_1\) \(R_1\)
\(S_2\) \(R_2\)
\(\vdots\)
\(S_N\) \(R_N\)
The first line contains an integer \(N\) representing the number of participants. In the following \(N\) lines, the \(i\)-th line contains a string \(S_i\) representing the name of the \(i\)-th participant and a string \(R_i\) representing their title, separated by a space.
【输出】
Output the rearranged list in \(N\) lines. The \(j\)-th line \((1 \leq j \leq N)\) should contain the name and honorific of the \(j\)-th participant after rearrangement, separated by a space. Note that the honorific is not the title itself, but sensei or san as determined by the rules above.
【输入样例】
4
alice student
bob teacher
carol other
dave doctor
【输出样例】
bob sensei
dave sensei
alice san
carol san
【核心思想】
-
问题分析:给定 \(N\) 位参会者,每人有姓名 \(S_i\) 和头衔 \(R_i\)。根据头衔将参会者分为 A 组(
teacher或doctor)和 B 组(student或other),A 组全部排在 B 组之前,组内保持输入顺序。A 组成员输出时加敬称sensei,B 组加san。这是一个直接模拟分组排序问题,关键在于按规则分类并保持相对顺序。 -
算法选择:
- 线性扫描分类:遍历所有参会者,根据头衔直接分配到 A 组或 B 组
- 稳定分组:使用
vector按输入顺序依次push_back,天然保持组内相对顺序 - 顺序输出:先遍历 A 组输出,再遍历 B 组输出
-
关键步骤:
- 读入 \(N\)
- 分类(遍历 \(i\) 从 \(1\) 到 \(N\)):
- 读入
name和title - 若
title == "teacher" || title == "doctor",加入groupA - 否则加入
groupB
- 读入
- 输出 A 组:遍历
groupA,每行输出name + " sensei" - 输出 B 组:遍历
groupB,每行输出name + " san"
-
时间/空间复杂度:
- 时间复杂度:\(O(N)\),线性遍历分类和输出
- 空间复杂度:\(O(N)\),存储两组参会者信息
-
直接模拟的核心思想:
- 规则映射:将头衔到分组的判断直接翻译为条件分支,无需复杂数据结构
- 稳定性的自然保证:按输入顺序依次加入
vector,输出时同样按顺序遍历,组内相对顺序自动保持 - 分组聚合:将"先输出 A 组再输出 B 组"的全局顺序要求,转化为两个独立容器的顺序拼接
- 适用于规则明确、无需复杂排序或查找的分类输出问题
【算法标签】
模拟
【代码详解】
#include <bits/stdc++.h>
using namespace std;
typedef pair<string, string> PII; // 定义PII为pair<string,string>,存储姓名和头衔
const int N = 200005; // 定义数组最大容量为200005
int n; // n为参会者数量
vector<PII> groupA; // groupA存储A组成员(teacher或doctor)
vector<PII> groupB; // groupB存储B组成员(student或other)
int main()
{
cin >> n; // 读入参会者数量n
for (int i = 1; i <= n; i++) // 依次读入每位参会者的信息
{
string name, title; // name为姓名,title为头衔
cin >> name >> title;
// 根据头衔分组:teacher或doctor归入A组,student或other归入B组
if (title == "teacher" || title == "doctor")
groupA.push_back({name, title}); // A组:输出时加敬称sensei
else
groupB.push_back({name, title}); // B组:输出时加敬称san
}
// 先输出A组所有成员(teacher和doctor),按输入顺序,敬称为sensei
for (auto x : groupA)
{
cout << x.first << " sensei" << endl; // x.first为姓名,输出"姓名 sensei"
}
// 再输出B组所有成员(student和other),按输入顺序,敬称为san
for (auto x : groupB)
cout << x.first << " san" << endl; // x.first为姓名,输出"姓名 san"
return 0;
}
【运行结果】
4
alice student
bob teacher
carol other
dave doctor
bob sensei
dave sensei
alice san
carol san
浙公网安备 33010602011771号