CSP-J 2025 第二轮 T2 座位 / seat 详细解析

P14358 [CSP-J 2025] 座位 / seat(官方数据)

题目描述

CSP-J 2025 第二轮正在进行。小 R 所在的考场共有 n×mn \times mn×m 名考生,其中所有考生的 CSP-J 2025 第一轮成绩互不相同。所有 n×mn \times mn×m 名考生将按照 CSP-J 2025 第一轮的成绩,由高到低蛇形分配座位,排列成 nnn mmm 。具体地,设小 R 所在的考场的所有考生的成绩从高到低分别为 s1>s2>⋯>sn×ms_1 > s_2 > \dots > s_{n \times m}s1>s2>>sn×m,则成绩为 s1s_1s1 的考生的座位为第 1 111 ,成绩为 s2s_2s2 的考生的座位为第 111 222 …\dots,成绩为 sns_nsn 的考生的座位为第 111 nnn ,成绩为 sn+1s_{n+1}sn+1 的考生的座位为第 222 nnn …\dots,成绩为 s2ns_{2n}s2n 的考生的座位为第 222 111 ,成绩为 s2n+1s_{2n+1}s2n+1 的考生的座位为第 333 111 ,以此类推。

例如,若 n=4,m=5n = 4, m = 5n=4,m=5,则所有 4×5=204 \times 5 = 204×5=20 名考生将按照 CSP-J 2025 第一轮成绩从高到低的顺序,根据下图中的箭头顺序分配座位。

:::align{center}

:::

给定小 R 所在的考场座位的行数 nnn列数 mmm,以及小 R 所在的考场的所有考生 CSP-J 2025 第一轮的成绩 a1,a2,…,an×ma_1, a_2, \dots, a_{n \times m}a1,a2,,an×m,其中 a1a_1a1 为小 R CSP-J 2025 第一轮的成绩,你需要帮助小 R 求出,他的座位为第几第几

输入格式

输入的第一行包含两个正整数 n,mn, mn,m,分别表示小 R 所在的考场座位的行数列数

输入的第二行包含 n×mn \times mn×m 个正整数 a1,a2,…,an×ma_1, a_2, \dots, a_{n \times m}a1,a2,,an×m,分别表示小 R 所在的考场的所有考生 CSP-J 2025 第一轮的成绩,其中 a1a_1a1 为小 R CSP-J 2025 第一轮的成绩。

输出格式

输出一行两个正整数 c,rc, rc,r,表示小 R 的座位为第 ccc rrr

输入输出样例 #1

输入 #1

2 2
99 100 97 98

输出 #1

1 2

输入输出样例 #2

输入 #2

2 2
98 99 100 97

输出 #2

2 2

输入输出样例 #3

输入 #3

3 3
94 95 96 97 98 99 100 93 92

输出 #3

3 1

说明/提示

【样例 1 解释】

按照成绩从高到低的顺序,成绩为 100100100 的考生的座位为第 111 111 ,成绩为 999999 的考生的座位为第 111 222 ,成绩为 989898 的考生的座位为第 222 222 ,成绩为 979797 的考生的座位为第 222 111 。小 R 的成绩为 999999,因此座位为第 111 222

【样例 2 解释】

按照成绩从高到低的顺序,成绩为 100100100 的考生的座位为第 111 111 ,成绩为 999999 的考生的座位为第 111 222 ,成绩为 989898 的考生的座位为第 222 222 ,成绩为 979797 的考生的座位为第 222 111 。小 R 的成绩为 989898,因此座位为第 222 222

【数据范围】

对于所有测试数据,保证:

  • 1≤n≤101 \leq n \leq 101n10, 1≤m≤101 \leq m \leq 101m10;
  • 对于所有 1≤i≤n×m1 \leq i \leq n \times m1in×m,均有 1≤ai≤1001 \leq a_i \leq 1001ai100,且 a1,a2,…,an×ma_1, a_2, \dots, a_{n \times m}a1,a2,,an×m 互不相同。

::cute-table{tuack}

测试点编号n≤n \leqnm≤m \leqm特殊性质
111111111AB
2,32, 32,3^101010
4,54, 54,5101010111^
666222222A
777^^B
8,98, 98,9^^
101010^101010A
111111^^B
12∼1412 \sim 141214^^
15∼1715 \sim 171517101010222^
18∼2018 \sim 201820^101010^

特殊性质 A:对于所有 1≤i≤n×m1 \leq i \leq n \times m1in×m,均有 ai=ia_i = iai=i

特殊性质 B:对于所有 1≤i≤n×m1 \leq i \leq n \times m1in×m,均有 ai=n×m−i+1a_i = n \times m - i + 1ai=n×mi+1

【模拟算法解题思路】

模拟算法解决这个问题,我们可以按照蛇形规则构建一个二维数组来表示座位分布,然后通过遍历数组找到小R的位置。具体步骤如下:

解题思路

  1. 获取输入并确定小R的成绩:读取考场的行数n、列数m,以及所有考生的成绩,其中第一个成绩是小R的成绩。
  2. 排序成绩:将所有成绩从高到低排序,因为座位是按成绩从高到低分配的。
  3. 模拟蛇形填充座位:按照蛇形规则(奇数列从上到下,偶数列从下到上),将排序后的成绩依次填入一个二维数组中,数组的行和列对应实际座位的行和列。
  4. 查找小R的位置:遍历填充好的二维数组,找到小R成绩所在的位置,输出对应的列号和行号。

C++实现代码

#include <iostream>
#include <algorithm>
using namespace std;

int main() {
    int n, m; // n行m列
    cin >> n >> m;
    int t = n * m; // 总人数
    int s[100]; // 存储所有成绩(最大10*10=100)
    for (int i = 0; i < t; ++i) {
        cin >> s[i];
    }
    int rs = s[0]; // 小R的成绩

    // 对成绩从高到低排序,存到ss数组
    int ss[100];
    for (int i = 0; i < t; ++i) ss[i] = s[i];
    sort(ss, ss + t, greater<int>());

    // 座位数组(m列n行,0-based索引)
    int seat[10][10]; // 最大10x10,满足题目范围

    // 按蛇形规则填充座位
    for (int c = 0; c < m; ++c) { // 遍历每一列(0-based)
        int ac = c + 1; // 实际列号(1-based)
        int si = c * n; // 该列在排序后数组中的起始索引
        for (int k = 0; k < n; ++k) { // 处理列中第k个元素
            int sc = ss[si + k]; // 当前要放置的成绩
            int r; // 行索引(0-based)
            if (ac % 2 == 1) { // 奇数列:从上到下(行号递增)
                r = k;
            } else { // 偶数列:从下到上(行号递减)
                r = n - 1 - k;
            }
            seat[c][r] = sc; // 放入座位
        }
    }

    // 查找小R的座位(转换为1-based输出)
    int rc, rr;
    for (int c = 0; c < m; ++c) {
        for (int r = 0; r < n; ++r) {
            if (seat[c][r] == rs) {
                rc = c + 1;
                rr = r + 1;
                break;
            }
        }
    }

    cout << rc << " " << rr << endl;
    return 0;
}

代码说明

  1. 输入处理:读取行数n、列数m和所有考生的成绩,其中第一个成绩是小R的成绩。
  2. 成绩排序:将成绩从高到低排序,因为座位分配顺序是按成绩从高到低进行的。
  3. 蛇形填充:创建一个mn行的二维数组,按列填充:
    • 奇数列(1-based)从上到下填充(行号从1到n)。
    • 偶数列(1-based)从下到上填充(行号从n到1)。
  4. 查找位置:遍历二维数组,找到小R成绩所在的位置,转换为1-based索引后输出列号和行号。

【数学规律解题思路】

思路分析

核心思想

  1. 蛇形排列规则

    • 奇数列:从上到下填充
    • 偶数列:从下到上填充
    • 按成绩从高到低依次分配座位
  2. 关键步骤

    • 确定小R在所有考生中的排名
    • 根据排名计算对应的行列位置
    • 考虑蛇形排列的特殊性

算法流程

  1. 统计比小R成绩好的人数,确定小R的排名
  2. 计算列号:(排名-1) / 行数 + 1
  3. 计算行号:根据列号的奇偶性决定计算方式

C++代码实现

#include <iostream>
using namespace std;

int main() {
    int n, m;  // 行数, 列数
    cin >> n >> m;
    
    int sz = n * m;  // 总人数
    int a[sz];       // 成绩数组
    
    // 读入成绩
    for (int i = 0; i < sz; i++) {
        cin >> a[i];
    }
    
    int rScore = a[0];  // 小R的成绩
    int cnt = 0;        // 比小R成绩好的人数
    
    // 统计比小R成绩好的人数
    for (int i = 0; i < sz; i++) {
        if (a[i] > rScore) {
            cnt++;
        }
    }
    
    int rk = cnt + 1;  // 小R的排名(从1开始)
    
    // 计算列号:每列n个人,从0开始计算
    int c = (rk - 1) / n + 1;
    
    // 计算行号
    int r;
    if (c % 2 == 1) {  // 奇数列:从上到下
        r = (rk - 1) % n + 1;
    } else {           // 偶数列:从下到上  
        r = n - (rk - 1) % n;
    }
    
    cout << c << " " << r << endl;
    return 0;
}

输入输出样例分析

样例1分析

输入: 2 2
      99 100 97 98
输出: 1 2
  • 成绩排序:100(1), 99(2), 98(3), 97(4)
  • 小R成绩99,排名第2
  • 第2个位置:第1列第2行(奇数列从上到下)

样例2分析

输入: 2 2
      98 99 100 97
输出: 2 2
  • 成绩排序:100(1), 99(2), 98(3), 97(4)
  • 小R成绩98,排名第3
  • 第3个位置:第2列第2行(偶数列从下到上)

样例3分析

输入: 3 3
      94 95 96 97 98 99 100 93 92
输出: 3 1
  • 小R成绩94,排名第7
  • 第7个位置:第3列第1行(奇数列从上到下)

关键点总结

  1. 排名计算:统计比小R成绩好的人数 + 1
  2. 列计算(排名-1)/行数 + 1(整数除法)
  3. 行计算:根据列号奇偶性采用不同计算方法
  4. 边界处理:注意数组索引从0开始,排名从1开始
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

信奥源老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值