//因为是在vs2019上面写的,部分scanf写成了scanf_s。

A-前M大的数

还记得Gardon给小希布置的那个作业么?(上次比赛的1005)其实小希已经找回了原来的那张数表,现在她想确认一下她的答案是否正确,但是整个的答案是很庞大的表,小希只想让你把答案中最大的M个数告诉她就可以了。
给定一个包含N(N<=3000)个正整数的序列,每个数不超过5000,对它们两两相加得到的N*(N-1)/2个和,求出其中前M大的数(M<=1000)并按从大到小的顺序排列。
Input
输入可能包含多组数据,其中每组数据包括两行:
第一行两个数N和M,
第二行N个数,表示该序列。
请在这里输入引用内容
Output
对于输入的每组数据,输出M个数,表示结果。输出应当按照从大到小的顺序排列。
Sample Input
4 4
1 2 3 4
4 5
5 3 6 4
Sample Output
7 6 5 5
11 10 9 9 8

直接暴力求解,算出所有情况,再sort排序,依次输出。

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

int res[3013500];
int main()
{
    int n, m, k;
    int num[3005];
    while (scanf("%d%d", &n, &m) != EOF) {
        k = 0;
        for (int i = 0; i < n; i++) {
            cin >> num[i];
        }
        for (int i = 0; i < n - 1; i++) {
            for (int j = i + 1; j < n; j++) {
                res[k] = num[i] + num[j];
                k++;
            }
        }
        sort(res, res + k);
        for (int i = k - 1; i > k - m; i--) {
            cout << res[i] << ' ';
        }cout << res[k - m] << endl;
    }
    return 0;
}

B - 稳定排序

大家都知道,快速排序是不稳定的排序方法。
如果对于数组中出现的任意a[i],aj,其中a[i]==a[j],在进行排序以后a[i]一定出现在a[j]之前,则认为该排序是稳定的。
请在这里输入引用内容
某高校招生办得到一份成绩列表,上面记录了考生名字和考生成绩。并且对其使用了某排序算法按成绩进行递减排序。现在请你判断一下该排序算法是否正确,如果正确的话,则判断该排序算法是否为稳定的。
Input
本题目包含多组输入,请处理到文件结束。
对于每组数据,第一行有一个正整数N(0<N<300),代表成绩列表中的考生数目。
接下来有N行,每一行有一个字符串代表考生名字(长度不超过50,仅包含'a'~'z'),和一个整数代表考生分数(小于500)。其中名字和成绩用一个空格隔开。
再接下来又有N行,是上述列表经过某排序算法以后生成的一个序列。格式同上。
Output
对于每组数据,如果算法是正确并且稳定的,就在一行里面输出"Right"。如果算法是正确的但不是稳定的,就在一行里面输出"Not Stable",并且在下面输出正确稳定排序的列表,格式同输入。如果该算法是错误的,就在一行里面输出"Error",并且在下面输出正确稳定排序的列表,格式同输入。
请在这里输入引用内容
注意,本题目不考虑该排序算法是错误的,但结果是正确的这样的意外情况。
Sample Input
3
aa 10
bb 10
cc 20
cc 20
bb 10
aa 10
3
aa 10
bb 10
cc 20
cc 20
aa 10
bb 10
3
aa 10
bb 10
cc 20
aa 10
bb 10
cc 20
Sample Output
Not Stable
cc 20
aa 10
bb 10
Right
Error
cc 20
aa 10
bb 10

利用结构体,编写sort排序,排序后进行比较,分情况输出结果。

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
struct P
{
    string name;
    int num, l;
}p[300];

bool cmp1(P a, P b)
{
    if (a.num == b.num)
        return a.l < b.l;
    else
        return a.num > b.num;
}

int main() {
    int n, k = 0;
    int num[300];
    char s[300][50];
    while (scanf_s("%d",&n)!=EOF)
    {
        k = 0;
        for (int i = 0; i < n; i++)
        {
            cin >> p[i].name >> p[i].num;
            p[i].l = i;
        }
        /*stable_*/sort(p, p + n, cmp1);
        for (int i = 0; i < n; i++)
        {
            cin >> s[i] >> num[i];
        }
        for (int i = 0; i < n; i++)
        {
            if (num[i] != p[i].num) {
                k = 1; break;
            }
            else if (num[i] == p[i].num && s[i] != p[i].name) {
                k = 2;
            }
        }
        if (k == 0)
            cout << "Right\n";
        else {
            if (k == 1)
                cout << "Error\n";
            else
                cout << "Not Stable\n";
            for (int i = 0; i < n; i++)
            {
                cout << p[i].name << ' ' << p[i].num << '\n';
            }
        }
    }
    return 0;
}

C - 开门人和关门人

每天第一个到机房的人要把门打开,最后一个离开的人要把门关好。现有一堆杂乱的机房签
到、签离记录,请根据记录找出当天开门和关门的人。
Input
测试输入的第一行给出记录的总天数N ( > 0 )。下面列出了N天的记录。
每天的记录在第一行给出记录的条目数M ( > 0 ),下面是M行,每行的格式为
请在这里输入引用内容
证件号码 签到时间 签离时间
请在这里输入引用内容
其中时间按“小时:分钟:秒钟”(各占2位)给出,证件号码是长度不超过15的字符串。
Output
对每一天的记录输出1行,即当天开门和关门人的证件号码,中间用1空格分隔。
注意:在裁判的标准测试输入中,所有记录保证完整,每个人的签到时间在签离时间之前,
且没有多人同时签到或者签离的情况。
Sample Input
3
1
ME3021112225321 00:00:00 23:59:59
2
EE301218 08:05:35 20:56:35
MA301134 12:35:45 21:40:42
3
CS301111 15:30:28 17:00:10
SC3021234 08:00:00 11:25:25
CS301133 21:45:00 21:58:40
Sample Output
ME3021112225321 ME3021112225321
EE301218 MA301134
SC3021234 CS301133

本题将编号,进入时间和出去的时间全部写成字符串,然后编写排序函数,使用sort排序,然后输出结果。

#include<iostream>
#include<algorithm>
#include<string>

using namespace std;

struct P
{
    string num, come, go;
}p[1000];

bool cmpr(P a, P b) {
    return a.come > b.come;
}
bool cmpc(P a, P b) {
    return a.go > b.go;
}

int main() {
    int n, m;
    char c,r;
    cin >> n;
    for (int i = 0; i < n; i++){
        cin >> m;
        for (int j = 0; j < m; j++){
            cin >> p[j].num >> p[j].come >> p[j].go;
        }
        sort(p, p + m, cmpr);
        cout << p[m - 1].num << ' ';
        sort(p, p + m, cmpc);
        cout << p[0].num << '\n';
    }
    return 0;
}

D - EXCEL排序

Excel可以对一组纪录按任意指定列排序。现请你编写程序实现类似功能。
Input
测试输入包含若干测试用例。每个测试用例的第1行包含两个整数 N (<=100000) 和 C,其中 N 是纪录的条数,C 是指定排序的列号。以下有 N
行,每行包含一条学生纪录。每条学生纪录由学号(6位数字,同组测试中没有重复的学号)、姓名(不超过8位且不包含空格的字符串)、成绩(闭区间[0, 100]内的整数)组成,每个项目间用1个空格隔开。当读到 N=0 时,全部输入结束,相应的结果不要输出。
Output
对每个测试用例,首先输出1行“Case i:”,其中 i 是测试用例的编号(从1开始)。随后在 N 行中输出按要求排序后的结果,即:当 C=1 时,按学号递增排序;当 C=2时,按姓名的非递减字典序排序;当 C=3
时,按成绩的非递减排序。当若干学生具有相同姓名或者相同成绩时,则按他们的学号递增排序。
Sample Input
3 1
000007 James 85
000010 Amy 90
000001 Zoe 60
4 2
000007 James 85
000010 Amy 90
000001 Zoe 60
000002 James 98
4 3
000007 James 85
000010 Amy 90
000001 Zoe 60
000002 James 90
0 0
Sample Output
Case 1:
000001 Zoe 60
000007 James 85
000010 Amy 90
Case 2:
000010 Amy 90
000002 James 98
000007 James 85
000001 Zoe 60
Case 3:
000001 Zoe 60
000007 James 85
000002 James 90
000010 Amy 90

本题同C题,编写排序函数并sort排序,输出结果。

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

struct P {
    string num, name;
    int gra;
}p[100005];
bool cmp1(P a, P b) {
    return a.num < b.num;
}
bool cmp2(P a, P b) {
    if(a.name!=b.name)
        return a.name < b.name;
    else
        return a.num < b.num;
}
bool cmp3(P a, P b) {
    if (a.gra != b.gra)
        return a.gra < b.gra;
    else
        return a.num < b.num;
}

int main() {
    int n, m, c=1;
    while (scanf_s("%d %d", &n, &m) != EOF) {
        if (n == 0)
            break;
        for (int i = 0; i < n; i++){
            cin >> p[i].num >> p[i].name >> p[i].gra;
        }
        if (m == 1)
            stable_sort(p, p + n, cmp1);
        if (m == 2)
            stable_sort(p, p + n, cmp2);
        if (m == 3)
            stable_sort(p, p + n, cmp3);
        printf("Case %d:\n", c++);
        for (int i = 0; i < n; i++)
        {
            cout << p[i].num <<' ' << p[i].name << ' '<< p[i].gra << '\n';
        }
    }
}

E - {A} + {B}

给你两个集合,要求{A} + {B}.
注:同一个集合中不会有两个相同的元素.
Input
每组输入数据分为三行,第一行有两个数字n,m(0<n,m<=10000),分别表示集合A和集合B的元素个数.后两行分别表示集合A和集合B.每个元素为不超出int范围的整数,每个元素之间有一个空格隔开.
Output
针对每组数据输出一行数据,表示合并后的集合,要求从小到大输出,每个元素之间有一个空格隔开.
Sample Input
1 2
1
2 3
1 2
1
1 2
Sample Output
1 2 3
1 2

本题使用set进行去重和排序,然后依次输出。

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

int main() {
    int n, m;

    while (scanf_s("%d%d", &n, &m) != EOF) {
        set<int> x;
        for (int i = 0; i < n; i++)
        {
            int j;
            cin >> j;
            x.insert(j);
        }
        for (int i = 0; i < m; i++)
        {
            int j;
            cin >> j;
            x.insert(j);
        }
        cout << *x.begin();
        x.erase(x.begin());
        while (!x.empty())
        {
            printf(" %d", *x.begin());
            x.erase(x.begin());
        }cout << '\n';
    }
    return 0;
}

F - 水果

夏天来了好开心啊,呵呵,好多好多水果
Joe经营着一个不大的水果店.他认为生存之道就是经营最受顾客欢迎的水果.现在他想要一份水果销售情况的明细表,这样Joe就可以很容易掌握所有水果的销售情况了.
Input
第一行正整数N(0<N<=10)表示有N组测试数据.
每组测试数据的第一行是一个整数M(0<M<=100),表示工有M次成功的交易.其后有M行数据,每行表示一次交易,由水果名称(小写字母组成,长度不超过80),水果产地(小写字母组成,长度不超过80)和交易的水果数目(正整数,不超过100)组成.
Output
对于每一组测试数据,请你输出一份排版格式正确(请分析样本输出)的水果销售情况明细表.这份明细表包括所有水果的产地,名称和销售数目的信息.水果先按产地分类,产地按字母顺序排列;同一产地的水果按照名称排序,名称按字母顺序排序.
两组测试数据之间有一个空行.最后一组测试数据之后没有空行.
Sample Input
1
5
apple shandong 3
pineapple guangdong 1
sugarcane guangdong 1
pineapple guangdong 3
pineapple guangdong 1
Sample Output
guangdong
|----pineapple(5)
|----sugarcane(1)
shandong
|----apple(3)

本题使用map,然后排序,依次输出。

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
struct P
{
    string s, t;
    int num;
}p[100];
bool cmp1(P a, P b) {
    if (a.t != b.t)
        return a.t < b.t;
    else
        return a.s < b.s;
}
int main() {
    int n, m, all = 0, js;
    string cd,cs;
    cin >> n;
    for (int j = 0; j < n; j++){
        cin >> m;
        for (int i = 0; i < m; i++){
            cin >> p[i].s >> p[i].t >> p[i].num;
        }
        all = 0;
        p[m].s = "-"; p[m].s = "-"; p[m].num = -1;
        sort(p, p + m, cmp1);
        cd = p[0].t; cs = p[0].s;
        cout << cd << '\n';
        for (int i = 0; i <= m; i++){
            if (p[i].s == cs) {
                all+= p[i].num;
            }
            else {
                cout << "   |----" << cs << '(' << all << ')';
                all = p[i].num;
                cs = p[i].s;
                if (j != n - 1)
                    if(i!=m)
                        cout << '\n';
                if (j == n - 1 && p[i].num != -1)
                    cout << '\n';
            }
            if (p[i].t != cd) {
                cd = p[i].t;
                cout << cd << '\n';
            }
        }if (j != n - 1)
                cout << '\n';
    }
    return 0;
}

G - 不重复数字

给出N个数,要求把其中重复的去掉,只保留第一次出现的数。
例如,给出的数为1 2 18 3 3 19 2 3 6 5 4,其中2和3有重复,去除后的结果为1 2 18 3 19 6 5 4。

Input
输入第一行为正整数T,表示有T组数据。
接下来每组数据包括两行,第一行为正整数N,表示有N个数。第二行为要去重的N个正整数。

Output

对于每组数据,输出一行,为去重后剩下的数字,数字之间用一个空格隔开。
Sample Input
2
11
1 2 18 3 3 19 2 3 6 5 4
6
1 2 3 4 5 6
Sample Output
1 2 18 3 19 6 5 4
1 2 3 4 5 6
Hint
对于30%的数据,1 <= N <= 100,给出的数不大于100,均为非负整数;
对于50%的数据,1 <= N <= 10000,给出的数不大于10000,均为非负整数;
对于100%的数据,1 <= N <= 50000,给出的数在32位有符号整数范围内。
提示:
由于数据量很大,使用C++的同学请使用scanf和printf来进行输入输出操作,以免浪费不必要的时间。

本题同上题,使用map进行解题。

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

int n, t, x;

map<int, int> p;

int main() {
    cin >> t;
    while (t--) {
        bool res = false;
        p.clear();
        cin >> n;
        for (int i = 1; i <= n; i++) {
            cin >> x;
            if (!p[x]) {
                p[x] = 1;
                if (!res) {
                    res = true;
                    cout << x;
                }
                else
                    cout << ' ' << x;
            }
        }
        cout << '\n';
    }
}

H - 表达式括号匹配

给出一个表达式,该表达式仅由字符(、)、+、-以及数字组成。

请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则返回"YES";否则返回"NO"。

输入格式
一行一个表达式,长度不超过
2000

若匹配,则输出"YES";否则输出"NO"

Sample Input
2+(3-4)-2-6)
Sample Output
NO

本题直接通过判断'('和')'的数量进行判断即可。

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

int n, t, x;

map<int, int> p;

int main() {
    cin >> t;
    while (t--) {
        bool res = false;
        p.clear();
        cin >> n;
        for (int i = 1; i <= n; i++) {
            cin >> x;
            if (!p[x]) {
                p[x] = 1;
                if (!res) {
                    res = true;
                    cout << x;
                }
                else
                    cout << ' ' << x;
            }
        }
        cout << '\n';
    }
}