坚持每日三题第8天:
目录
题目一:
题目大意:
现在有一个长度为n的数组a,现在你可以进行以下操作任意次:
选择数组中的一个元素a[i],将a[i]减少任意的数,最少减少到1。
定义MEX(a)为不在数组a中的最小正整数。
现在你需要进行任意次操作,使得数组a的MEX值尽可能大,输出这个最大值。
解题思路:
注意题目中的MEX是最小正整数,不包含0的
所以我们得从1开始找。
我们每次可以把数组中的一个数字减小任意的数量。
我们很明显可以发现,假设数字全是无穷大,
此时MEX的值肯定是数组长度加1,因为可以把这些数字全部变成1到n。
那么我们可以发现这样的求解思路:
从小到大排序数组,设x = 1
从1开始找,每次找到比x大的数字,表示可以把这个数字减少到x。
此时MEX(a) = x + 1。
具体实现看代码
代码(C++):
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
}
//排序
std::ranges::sort(a);
//从1开始贪心的找
int ans = 1;
for (int& x : a) {
//每次找到一个比当前大的,表示可以把这个缩小到ans
//此时MEX为ans + 1
if (x >= ans) {
ans++;
}
}
std::cout << ans << "\n";
}
题目二:
题目大意:
现在两个玩家A, B进行游戏,他们刚开始各有一个数组,分别为a, b。
现在玩家A, B刚开始得分都为0,现在从A开始先手进行游戏。
各自的回合,他们可以选择以下两个操作其中一个进行操作:
1.选择自己数组中的一个数字,删除并把这个数字加在自己的分数上。
2.选择对方数组中的一个数字,删除。
现在两个玩家都用最优的操作,并且要使得得分之差尽可能大。
解题思路:
这个题目其实很明显的思路了,不过实现稍微有点麻烦了,我这里用的简单易懂的方法实现的。
最优策略:
如果都有数字,那么比较最大的那个,如果自己的大,就拿自己的,如果对面的大,就删除对面的。
具体实现看代码
代码(C++):
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n), b(n);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
}
for (int i = 0; i < n; i++) {
std::cin >> b[i];
}
std::ranges::sort(a, std::greater<int>());
std::ranges::sort(b, std::greater<int>());
i64 s1 = 0, s2 = 0;
int i = 0, j = 0;
while (i < n || j < n) {
//玩家A进行操作
//两个玩家数组中都有数字的情况
if (i < n && j < n) {
if (a[i] > b[j]) {
s1 += a[i];
i++;
} else {
j++;
}
} else if (i >= n && j < n) {
//玩家A没有数字了,但是玩家B有数字
j++;
} else if (i < n && j >= n) {
//玩家A有数字,但是玩家B没数字
s1 += a[i];
i++;
}
//玩家B进行操作
if (i < n && j < n) {
if (b[j] > a[i]) {
s2 += b[j];
j++;
} else {
i++;
}
} else if (i >= n && j < n) {
s2 += b[j];
j++;
} else if (i < n && j >= n) {
i++;
}
}
std::cout << s1 - s2 << "\n";
}
题目三:
题目大意:
现在有一个长度为n的数组a,玩家A和B进行游戏,现在A已经把从前往后进行的元素分配:
在这里,给你一个长度为n的字符串S,只包含字符A和B,对于一个下标i。
如果S[i] == ’A‘,表示a[i]为玩家A的数字。
现在玩家B可以进行下述操作一次:
选择数组中的任何一个前缀或者后缀,把对应的数字归属情况进行翻转。
现在玩家的得分为属于自己的数字和。
现在你需要找出,B能获得的最大得分。
解题思路:
代码(C++):
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
}
std::string s;
std::cin >> s;
std::vector<i64> prefA(n + 1), prefB(n + 1);
for (int i = 1; i <= n; i++) {
prefA[i] = prefA[i - 1];
prefB[i] = prefB[i - 1];
if (s[i - 1] == 'A') {
prefA[i] += a[i - 1];
} else {
prefB[i] += a[i - 1];
}
}
i64 ans = prefA[n];
for (int i = 1; i <= n; i++) {
ans = std::max(ans, prefA[n] - prefA[i] + prefB[i]);
}
for (int i = n; i >= 1; i--) {
ans = std::max(ans, prefB[n] - prefB[i] + prefA[i]);
}
std::cout << ans << "\n";
}
Python语言写法:
题目一:
def solve():
n = II()
a = LII()
a.sort()
ans = 1
for x in a:
if x >= ans:
ans += 1
print(ans)
题目二:
def solve():
n = II()
a = LII()
b = LII()
a.sort(reverse=True)
b.sort(reverse=True)
s1, s2 = 0, 0
i, j = 0, 0
while i < n or j < n:
if i < n and j < n:
if a[i] > b[j]:
s1 += a[i]
i += 1
else:
j += 1
elif i >= n and j < n:
j += 1
elif i < n and j >= n:
s1 += a[i]
i += 1
if i < n and j < n:
if b[j] > a[i]:
s2 += b[j]
j += 1
else:
i += 1
elif i >= n and j < n:
s2 += b[j]
j += 1
elif i < n and j >= n:
i += 1
print(s1 - s2)
题目三:
def solve():
n = II()
a = LII()
s = I()
pref_a = [0] * (n + 1)
pref_b = [0] * (n + 1)
for i in range(1, n + 1):
pref_a[i] = pref_a[i - 1]
pref_b[i] = pref_b[i - 1]
if s[i - 1] == 'A':
pref_a[i] += a[i - 1]
else:
pref_b[i] += a[i - 1]
ans = pref_a[n]
for i in range(1, n + 1):
ans = max(ans, pref_a[n] - pref_a[i] + pref_b[i])
for i in range(1, n + 1):
ans = max(ans, pref_b[n] - pref_b[i] + pref_a[i])
print(ans)