题目
题解
模拟。
之所以样例输出如此,是因为第一行其实是排队的最后一排,样例的输出更像是一张俯视图,我们站在最后一行的下一行去给他们拍照,他们面朝下,我们面朝上。
至于题目中说的“这里假设你面对拍照者,所以你的左边是中间人的右边”,就理解成每行都是按照先选出最高的人,队伍的最左端(我们的视角)插入一个次高的,再向队伍右端插入一个次次高的……
先排序。
我是以步长为2分别从右向左、从左向右遍历排好序的每个人,直接输出就行了;但是要注意分该行的人数是奇数还是偶数,奇数和偶数对应的遍历边界不一样。
为什么我实现代码这么慢?脑子太笨,沃日。
代码
#include<bits/stdc++.h>
using namespace std;
int n, k, m, l;
struct node {
string name;
int h;
} a[10010];
bool cmp (node a, node b) {
if (a.h != b.h) return a.h > b.h;
return a.name < b.name;
}
int main()
{
cin >> n >> k;
for (int i = 0;i < n;i ++) cin >> a[i].name >> a[i].h;
sort (a, a+n, cmp);
for (int t = 0;t < k;t ++) {
m = n / k + n % k; // 该行的人数
n -= n % k; // 如果n整除k了每次n就不变了
int r = l + m - 1, flag = 0; // l和r分别控制该行人的索引的左端点与右端点
// cout << l << ' ' << r << endl;
for (int i = r - (m & 1);i >= l;i -= 2) { // 每次隔着一个人枚举,如果该行的人数为奇数,那么就要从r的前一个开始向前推
if (flag) cout << ' ';
flag = 1;
cout << a[i].name;
}
for (int i = l;i <= r;i += 2) { // 也是每次隔一个人
if (flag) cout << ' ';
flag = 1;
cout << a[i].name;
}
l = r + 1; // 更新l
cout << endl;
}
return 0;
}