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;
}