第二届太原理工大学程序设计新生赛预赛(公开赛)题解

A题
链接:https://ac.nowcoder.com/acm/contest/3121/A
来源:牛客网

Creeper?
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld
题目描述
这是一个简单的接龙游戏。

如果有人说"Creeper?"(不包括两侧的双引号,下同),下一个人需要说"Awww man."。

如果有人说"Awww man.",下一个人需要说"Se no!".

如果有人说"Se no!",下一个人需要说"Creeper?".
输入描述:

输入数据有N组,每组数据占一行,每行保证为"Creeper?"、“Awww man.”、"Se no!"三者之一(不包括双引号)。

  • 1≤N≤100.

输出描述:

按照题目描述中的规则输出相应的字符串完成接龙,第i行的输出对应输入的第i + 1行的结果,举个例子,如果输入的一行为"Creeper?",你的程序需要在一行输出"Awww man."。

为了使接龙更容易成功,你的输出可以不区分大小写,如对于输入的"Creeper?",你的程序输出"awww man."、"aWwW mAn."都会被认为是正确的。

示例1
输入

2
Creeper?
Se no!

输出

Awww man.
creeper?

示例2
输入

3
Creeper?
Awww man.
Awww man.

输出

awww man.
se no!
se NO!

解题后记:需要用到模除,这样程序逻辑也许比较简单。语句的开始字符不同时,可以考虑用字符比较代替字符串比较。

AC的C语言程序如下:

#include <stdio.h>
#include <string.h>

#define N 3
char *ps[] = {"Creeper?", "Awww man.", "Se no!"};

int main()
{
    int n, i;
    char s[10];
    
    scanf("%d", &n);
    getchar();
    
    while(n--) {
        gets(s);
        for(i = 0; i < N; i++)
            if(strcmp(s, ps[i]) == 0) break;
        
        printf("%s\n", ps[(i + 1) % N ]);
    }
}

AC的C++语言程序如下:

#include <iostream>
#include <algorithm>
#include <cstdio>

using namespace std;

const int N = 3;
string word[] = {"Creeper?", "Awww man.", "Se no!"};

int main()
{
    int n, i;
    string s;

    scanf("%d", &n);
    getline(cin, s);

    while(n--) {
        getline(cin, s);
        for(i = 0; i < N; i++)
            if(s[0] == word[i][0]) break;

        printf("%s\n", word[(i + 1) % N ].c_str());
    }
}

D题
链接:https://ac.nowcoder.com/acm/contest/3121/D
来源:牛客网

Imperishable Night
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld
题目描述
在地图的帮助下,Vanis在那个夜晚 (the splendid diamonds night) 找到了许多的钻石,但是夜晚却迟迟未结束,似乎是因为某种异变,不过这都与Vanis无关,Vanis十分无聊,于是他找到n个空盒子放在桌上,排成一排,从左到右依次从1编号到n,之后,Vanis会做多次操作,对于第i次操作,他会在从编号为li​到ri​的所有盒子(包括li​和ri​)中各放入wi​颗钻石。

最后他想知道从左到右每个盒子中各有多少颗钻石。
输入描述:

第一行包含两个正整数n和q,之间使用一个空格符分隔,分别为盒子的数目以及操作的次数。
第二行开始连续q行,每行包含三个整数,相邻整数之间使用一个空格符分隔,这样输入的第i行的三个整数按照输入顺序记作li​, ri​, ki​。

数据规范:

  • 1≤n≤106.
  • 1≤q≤106.
  • li​≤ri​.
  • 0≤ki​≤106.
  • 1≤li​, ri​≤n.
  • 保证完成所有操作后全部盒子中的钻石数目之和不超过109.

输出描述:

输出一行,包含n个整数,相邻整数之间使用一个空格符分隔,输出的第i个整数表示编号为i的盒子中的钻石个数。

示例1
输入

5 3
1 1 2
1 2 1
1 3 1

输出

4 2 1 0 0

备注:

大量输入,注意使用较快速的输入输出方式。

解体后记:暴力法是解决不了问题的,会超时。本题需要根据前缀和的原理来解。

AC的C语言程序如下:

#include <stdio.h>
#include <string.h>

#define N 1000000
int a[N + 2];

int main(void)
{
    int n, q, l, r, k, i;

    scanf("%d%d", &n, &q);
    memset(a, 0, sizeof(int) * (n + 1));
    while(q--) {
        scanf("%d%d%d", &l, &r, &k);
        a[l] += k;
        a[r + 1] -= k;
    }

    for(i = 1; i <= n; i++) {
        a[i] += a[i - 1];
        if(i != 1) printf(" ");
        printf("%d", a[i]);
    }
    printf("\n");

    return 0;
}

TLE的C语言程序如下:

#include <stdio.h>
#include <string.h>

#define N 1000000
int cnt[N + 1];

int main(void)
{
    int n, q, l, r, k, i;

    scanf("%d%d", &n, &q);
    memset(cnt, 0, sizeof(int) * (n + 1));
    while(q--) {
        scanf("%d%d%d", &l, &r, &k);
        for(i = l; i <= r; i++)
            cnt[i] += k;
    }

    for(int i = 1; i <= n; i++) {
        if(i != 1) printf(" ");
        printf("%d", cnt[i]);
    }
    printf("\n");

    return 0;
}

E题
链接:https://ac.nowcoder.com/acm/contest/3121/E
来源:牛客网

Mysterious Mountain
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld
题目描述

有一座神秘的山,村民无法随便走进这座山,因此对山中情况有不少传言。

某日,Vanis去寻找这座山,根据传言,这座山是周围众多山峰中第三高的那一座,但是周围层峦叠嶂,隐天蔽日,正所谓“只缘身在此山中”,Vanis想希望你能帮他找到,当然你只需要告诉他这座山的高度即可。
输入描述:

第一行输入一个正整数n,表示山峰的个数。
第二行输入n个正整数,第i个记作hi​,表示第i座山的高度,相邻整数之间使用一个空格符分隔。

数据规范:

  • 3≤n≤106.
  • 1≤hi​≤1000.

输出描述:

输出有一行,输出n个数中第三大的数。

示例1
输入

3
1 2 3

输出

1

示例2
输入

5
1 3 5 7 9

输出

5

示例3
输入

9
9 9 9 9 9 9 9 9 9

输出

9

解题后记:求第k大数问题,可以看参考链接。用排序算法函数partial_sort()来实现应该最为简单,也可以用算法函数nth_element()实现。
参考链接
AOJ0001 List of Top 3 Hills【水题】
HDU1425 sort【排序】

AC的C语言程序如下:

#include <stdio.h>
#include <limits.h>
 
int main(void)
{
    int n, a, max1, max2, max3, temp, i;
 
    max1 = max2 = max3 = INT_MIN;
    scanf("%d", &n);
    for(i = 1; i <= n; i++) {
        scanf("%d", &a);
        if(a > max3) {
            max3 = a;
 
            /* 排序 */
            if(max3 > max1) {
                temp = max3;
                max3 = max2;
                max2= max1;
                max1 = temp;
            } else if(max3 > max2) {
                temp = max3;
                max3 = max2;
                max2 = temp;
            }
        }
    }
 
    printf("%d\n", max3);
 
    return 0;
}

AC的C语言程序如下:

#include <iostream>
#include <algorithm>

using namespace std;

const int MAXN = 1000000;
int a[MAXN];

int main(void)
{
    int n;

    // 读入数据
    scanf("%d", &n);
    for(int i=0; i < n; i++)
        scanf("%d", &a[i]);

    // 排序
    partial_sort(a, a + 3, a + n, greater<int>());

    // 输出结果
    printf("%d\n", a[2]);

    return 0;
}

AC的C语言程序如下:

#include <iostream>
#include <algorithm>

using namespace std;

const int MAXN = 1000000;
int a[MAXN];

int main(void)
{
    int n;

    // 读入数据
    scanf("%d", &n);
    for(int i=0; i < n; i++)
        scanf("%d", &a[i]);

    // 求第n大元素
    nth_element(a, a + 2, a + n, greater<int>());

    // 输出结果
    printf("%d\n", a[2]);

    return 0;
}

AC的C语言程序如下:

#include <iostream>
#include <algorithm>

using namespace std;

const int MAXN = 1000000;
int a[MAXN];

int main(void)
{
    int n;

    // 读入数据
    scanf("%d", &n);
    for(int i=0; i < n; i++)
        scanf("%d", &a[i]);

    // 求第n大元素
    nth_element(a, a + n - 3, a + n);

    // 输出结果
    printf("%d\n", a[n - 3]);

    return 0;
}

F题
链接:https://ac.nowcoder.com/acm/contest/3121/F
来源:牛客网

Cirno’s Perfect Algorithm Class
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld
题目描述
Cirno (⑨) 非常聪明。

在某个炎热的夏季,Cirno找到了一堆冰块,并将冰块摆成一排,她想将冰块从左到右按照从小到大排序,因为她非常“聪明”,所以她每次只能交换相邻的两个冰块。
夏日的天气十分炎热,如果动作太慢,冰块就化掉了,Cirno也就无法再完成她的目标。所以Cirno想知道最少需要多少次交换能够将冰块从小到大排好序。

形式化地说,给出一个长度为n的序列,如果只允许“交换相邻两个元素”这一种操作,问最少需要多少次操作能够使序列从小到大排好序。
输入描述:

第一行输入一个正整数n,表示冰块的数量。
第二行输入n个正整数,第i个正整数记作si​,表示从左到右第i个冰块的大小。

数据规模:

  • 1≤n≤100.
  • 1≤si​≤100.

输出描述:

输出一个正整数,表示最小交换次数。

示例1
输入

5
5 4 3 2 1

输出

10

示例2
输入

3
1 2 3

输出

0

示例3
输入

4
3 1 2 4

输出

2

说明
在这里插入图片描述
示例4
输入

4
3 1 2 3

输出

2

示例5
输入

4
3 1 3 3

输出

1

解体后记:逆序数问题,参见参考链接。要想算得快,只能使用归并排序的算法思想。
参考链接POJ1804 Brainman【逆序偶+归并排序】

AC的C语言程序如下:

#include <iostream>
#include <stdio.h>
 
using namespace std;
 
const int N = 100;
int a[N], temp[N], cnt;
 
void merge(int low, int mid, int high)
{
    int i = low, j=mid+1, k = low;
    while(i <= mid && j <= high)
    {
        if(a[i] <= a[j])
            temp[k++] = a[i++];
        else {
            cnt += j - k;
            temp[k++] = a[j++];
        }
    }
    while(i <= mid)
        temp[k++] = a[i++];
    while(j <= high)
        temp[k++] = a[j++];
    for(i=low; i<=high; i++)
         a[i] = temp[i];
}
 
void mergesort(int low, int high)
{
    if(low < high)
    {
        int middle = (low + high) / 2;
        mergesort(low, middle);
        mergesort(middle+1, high);
        merge(low, middle, high);
    }
}
 
int main()
{
    int n;

    scanf("%d", &n);
    for(int i = 0; i < n; i++)
        scanf("%d", &a[i]);
 
    cnt = 0;
    mergesort(0, n - 1);
 
    printf("%d\n", cnt);
 
    return 0;
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值