2023年7月6日普及组南外集训题解
A 阿伦
因为相邻的穿同样衣服的人只要走了一个就会全走,所以我们可以定义一个char数组,只要当前的与上一个不同,答案就加一
#include <iostream>
using namespace std;
int main() {
int n, ans = 0;
char c0 = ' ', c1;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> c1;
if (c0 != c1)
ans++;
c0 = c1;
}
cout << ans + 1;
return 0;
}
B 二八杠
由于本题需要判断的东西非常多,非常容易遗漏,如果使用常用的if else可能会有遗漏导致错误,所以我们可以给每种操作赋一个权值,这样在判断是就会非常方便,但是要注意关于权值的问题
注:\((x+y)\%10*10\)的原因是因为\(x,y\)的和的个位数有可能小于原本的数
#include <iostream>
using namespace std;
int cal(int x, int y) {
if (x > y)
swap(x, y);
if (x == 2 && y == 8)
return 1000;
else if (x == y)
return 900;
else
return (x + y) % 10 * 10 + y;
}
int main() {
int n;
cin >> n;
while (n--) {
int a1, a2, b1, b2;
cin >> a1 >> a2 >> b1 >> b2;
if (cal(a1, a2) == cal(b1, b2))
puts("tie");
else if (cal(a1, a2) > cal(b1, b2))
puts("first");
else
puts("second");
}
return 0;
}
C 编程考试
我们可以使用前缀和优化这个问题,首先开一个二维数组,存储每个位置上的字母,用string
读入,注意string
的下标是从0
开始的
#include <iostream>
using namespace std;
int word_count[50005][26];
string s;
int q;
int main() {
cin >> s;
for (int i = 1; i <= s.length() - 1; i++) {
for (int j = 0; j < 26; j++) {
word_count[i][j] = word_count[i - 1][j];
}
word_count[i][s[i - 1] - 'a']++;
}
cin >> q;
while (q--) {
int a, b, c, d;
cin >> a >> b >> c >> d;
bool flag = true;
for (int i = 0; i < 26; i++) {
if (word_count[b][i] - word_count[a - 1][i] != word_count[d][i] - word_count[c - 1][i]) {
flag = false;
break;
}
}
puts(flag ? "DA" : "NE");
}
return 0;
}
D 01反转
首先我们可以先定义一个数组,意在获得连续的一段数字有几个,这样可减低我们的时间复杂度
接下来我们将这个数组进行累加,两个之间夹着的就是我们的答案,我们要先判断一下是从0还是1开始,如果是1,遍历的时候i要加一
我们的数组要另开2*k个,原因如下图:
#include <iostream>
#include <cstring>
using namespace std;
const int M = 2e5 + 7;
int n, k, cnt = 0, pre[M], ans = 0;
string s;
int main() {
cin >> n >> k;
cin >> s;
pre[++cnt] = 1;
for (int i = 1; i < n; i++) {
if (s[i] != s[i - 1])
pre[++cnt] = 1;
else
pre[cnt]++;
}
for (int i = 1; i <= cnt + 2 * k; i++) pre[i] += pre[i - 1];
int i = 0 + ((s[0] - '0') == 1);
while (i <= cnt) {
ans = max(ans, pre[i + 2 * k] - pre[i - 1]);
i += 2;
}
cout << ans;
return 0;
}
E 愉悦的晚餐
这个问题\(n\)的范围很大,用dfs或二进制枚举只能拿到50%的分,所以我们要进行优化
进过枚举我们可以发现值的排列一共有8种,这对于我们后面求绝对值有帮助
之后我们根据初中数学可以得知,绝对值的结果分为两种,之后我们便可简单解答
如下图:
所以我们算的时候直接分8种:
calc(1, 1, -1);
calc(1, -1, -1);
calc(1, -1, 1);
calc(1, 1, 1);
calc(-1, 1, 1);
calc(-1, -1, 1);
calc(-1, -1, -1);
calc(-1, 1, -1);
#include <bits/stdc++.h>
using namespace std;
long long n, m, a[1005], b[1005], c[1005], s[1005];
long long ans = -1e15;
bool cmp(long long x, long long y) { return x > y; }
void calc(int af, int bf, int cf) {
long long ret = 0;
for (int i = 1; i <= n; i++) {
s[i] = af * a[i] + bf * b[i] + cf * c[i];
}
sort(s + 1, s + n + 1, cmp);
for (int i = 1; i <= m; i++) ret += s[i];
ans = max(ans, ret);
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i] >> b[i] >> c[i];
}
calc(1, 1, -1);
calc(1, -1, -1);
calc(1, -1, 1);
calc(1, 1, 1);
calc(-1, 1, 1);
calc(-1, -1, 1);
calc(-1, -1, -1);
calc(-1, 1, -1);
cout << ans;
return 0;
}
F 买蛋糕
首先我们用暴力是解决不了这个问题的,我们要优美地解决
考虑到最终答案要求我们从大到小输出,我们自然就能想到优先队列的大根堆
这样最大值就直接输出根就可以了
另外我们需要定义一个结构体方便我们的存储,并在里面重载运算符,否则会导致stl的使用报错
bool operator < (const cake &A) const
{
return a[x]+b[y]+c[z]<a[A.x]+b[A.y]+c[A.z];
}
关于优先队列如何使用可以参考 c++优先队列(priority_queue)用法详解
排序完之后便开始输出答案,首先输出根部,然后再进行拓展,分别是\(x+1,y+1,z+1\),记得用map打上标记,以免重复
#include <iostream>
#include <queue>
#include <algorithm>
#include <map>
using namespace std;
const int N = 1e3 + 10;
long long a[N], b[N], c[N];
int x, y, z, k;
struct cake {
int x, y, z;
bool operator<(const cake &A) const { return a[x] + b[y] + c[z] < a[A.x] + b[A.y] + c[A.z]; }
};
priority_queue<cake> q;
map<pair<pair<int, int>, int>, bool> mp;
bool cmp(long long a, long long b) { return a > b; }
int main() {
scanf("%d%d%d%d", &x, &y, &z, &k);
for (int i = 1; i <= x; i++) cin >> a[i];
for (int i = 1; i <= y; i++) cin >> b[i];
for (int i = 1; i <= z; i++) cin >> c[i];
sort(a + 1, a + x + 1, cmp);
sort(b + 1, b + x + 1, cmp);
sort(c + 1, c + x + 1, cmp);
q.push((cake){ 1, 1, 1 });
mp[make_pair(make_pair(1, 1), 1)] = true;
for (int i = 1; i <= k; i++) {
cake t = q.top();
q.pop();
printf("%lld\n", a[t.x] + b[t.y] + c[t.z]);
if (!mp.count(make_pair(make_pair(t.x + 1, t.y), t.z)) && t.x < x) {
mp[make_pair(make_pair(t.x + 1, t.y), t.z)] = true;
q.push((cake){ t.x + 1, t.y, t.z });
}
if (!mp.count(make_pair(make_pair(t.x, t.y + 1), t.z)) && t.y < y) {
mp[make_pair(make_pair(t.x, t.y + 1), t.z)] = true;
q.push((cake){ t.x, t.y + 1, t.z });
}
if (!mp.count(make_pair(make_pair(t.x, t.y), t.z + 1)) && t.z < z) {
mp[make_pair(make_pair(t.x, t.y), t.z + 1)] = true;
q.push((cake){ t.x, t.y, t.z + 1 });
}
}
return 0;
}