「暴力」Med

本题为12月22日22寒假集训每日一题题解

题目来源:COCO_2022.4.9

题面

题目描述

The moment has finally arrived. Not only is it the last round of COCI this season, it is also the last round of COCB – the Croatian Open Competition in Beekeeping. Not manypeople know that the two competitions share the same scoring system. More precisely, both competitions consist of six rounds, the points on each round are between 0 and 500, and the scores of the individual rounds are summed up for the final tally.

After the six rounds, the competitors are ranked based on their total score over the six rounds. If two competitors have the same score, the one with the lexicographically smaller name appears sooner on the ranking. No two competitors have the same name.

The beekeepers are very impatient and they would like to know what their final ranking will be in advance.

Each beekeeper wants to know their best and worst possible positions on the final ranking. Unlike skilled COCI programmers, the beekeepers don’t know how to code. Therefore, they are asking you to determine the range of positions they could occupy after the sixth round.

输入

The first line contains a positive integer n (1 ≤ n ≤ 500), the number of beekeepers.

Each of the following n lines contains the name of a beekeeper si (1 ≤ |si | ≤ 10) and five numbers bi1, bi2, bi3, bi4, bi5 from the range [0, 500], the scores of the i-th beekeeper on the first five rounds of COCB.

The names of the beekeepers are distinct and are made up of at most ten lowercase letters of the latin alphabet.

输出

Print n lines. In the i-th line print the best and worst possible position on the ranking for the i-th beekeeper.

样例输入

【样例输入1】
3
pavel 120 200 300 400 500
keko 150 400 300 200 100
bartol 470 120 90 93 189
【样例输入2】
2
ante 275 275 275 275 275
mate 25 100 175 250 325

样例输出

【样例输出1】
1 2
1 3
2 3
【样例输出2】
1 1
2 2

提示

Clarification of the second example:

So far, Ante has a sum of 1375, and Mate has 875. If Mate were to win 500 points on the last round, and Ante 0, the result would be tied and they would both have 1375 points. However, since Ante is lexicographically smaller than Mate, Ante will still be ahead on the ranking


思路分析

本题看完题目后的第一思路想必应该都是找出最佳和最差的情况,分别进行排序,然后看看排在第几位即可.

那什么是最佳和最差的情况呢?显然,下一场当前人取得所有分数,而其他人0分,为最佳情况;而下一场当前人0分,而其他人取得所有分数,为最差情况,此时相当于当前人取得-500分.所以只需要对当前人的总分分别+500和-500,然后排序,看看在第几位即可.此题数据量较小,用此方法即可通过.

进一小步思考,其实此题只需要知道排名,并不需要进行排序,所以上述思路中的排序可以去掉,直接遍历整个数组,根据有几个人的总分比自己大(总分相同时字典序小)即可得到当前在第几位,由于此处两个关键字的顺序是不同的,所以pair自带的<不能使用,需要手动重载<运算符.

参考代码

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3, "Ofast", "inline")

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// 排位是分数为主关键字降序,字典序为副关键字升序,所以需要重载pair的<运算符(最好把>也重载了)
bool operator<(pair<int, string> a, pair<int, string> b)
{
    return a.first == b.first ? a.second > b.second : a.first < b.first;
}

int main()
{
    ios::sync_with_stdio(false);

    // 输入数据
    int n;
    cin >> n;
    vector<pair<int, string>> a(n, make_pair(0, ""));
    for (int i = 0; i < n; i++)
    {
        cin >> a[i].second;
        int b;
        for (int j = 0; j < 5; j++)
        {
            cin >> b;
            a[i].first += b;
        }
    }

    // 逐个处理
    for (int i = 0; i < n; i++)
    {
        int res1 = 1, res2 = 1;     // res1为最佳排名,res2为最差排名
        for (int j = 0; j < n; j++) // 遍历整个数组确认排名
        {
            a[i].first += 500; // 下一场当前人取得所有分数,而其他人0分,为最佳情况
            if (a[i] < a[j])   // 存在比当前大的,排名要后一名
            {
                res1++;
            }

            a[i].first -= 1000; // 下一场当前人0分,而其他人取得所有分数,为最差情况,此时相当于当前人取得-500分
            if (a[i] < a[j])    // 存在比当前大的,排名要后一名
            {
                res2++;
            }
            a[i].first += 500; // 当前分数归位
        }
        cout << res1 << " " << res2 << "\n";
    }

    return 0;
}

“正是我们每天反复做的事情,最终造就了我们,优秀不是一种行为,而是一种习惯” —亚里士多德