[算法训练] 1114Div3-①B-模拟②C2-贪心③D-构造
1114Div3-①B-模拟②C2-贪心③D-构造
Dashboard - Codeforces Round 1114 (Div. 3) - Codeforces
A-模拟
题目
爱丽丝、鲍勃和查理正在玩一个代币游戏。他们开始时分别有 a 、 b 和 c 个代币。
游戏分轮进行。在每一轮开始之前,他们都要检查每个人拥有的代币数:
- 如果任何两名玩家拥有的代币数量完全相同,游戏立即结束。
- 否则,一轮游戏开始时,三位玩家拥有的代币数量完全不同。拥有最多代币的玩家给拥有最少代币的玩家 1 个代币。
给定起始代币为 a 、 b 和 c ,请确定游戏到底要进行多少轮才会结束
模拟
对a,b,c进行排序,假设a≤b≤c,每次操作使a+=1,c-=1,a和c都趋向于b,那么显然答案为min(b - a,c - b)
#include <bits/stdc++.h>using namespace std;int main() { int t; cin >> t; while(t--) { vector<int> v(3); for(int &x : v) cin >> x; sort(v.begin(), v.end()); cout << min(v[2] - v[1], v[1] - v[0]) << endl; }}B-模拟
题目
让 f(s) 成为字符串 s 的压缩版本,将每个最大连续字符块中的相同字符替换为该字符的单个副本。例如, f( “aabbcc” ) = “abc”。 “abc”。
让 |s| 表示字符串 s 的长度。接着, |f(s)| 表示压缩字符串的长度。例如
- |f( “aabbcc” )|= 。 | “abc” | =3
- 如果字符串为空,其长度为 0 。
优素福给了您一个由 n 个小写拉丁字母组成的字符串 s 。您必须准确删除1个字符 si ( 2≤i≤n−1 )以组成新字符串 s′ ,然后找出 |f(s′)| 的最小可能值。
注意不能删除 s1 或 sn 。
模拟
在删除字符时,考虑该字符左侧和右侧的字符,若他们相同,则答案会减少2;否则答案减少1
#include<bits/stdc++.h>using namespace std;int main(){ int t; cin >> t; while(t--){ int n; cin >> n; string s; cin >> s; int ans = 1,x = 0; for(int i = 1;i < n;i++){ if(s[i] != s[i-1]){ ans++; } if(i == n - 1){ break; } if(s[i] != s[i-1] && s[i] != s[i+1]){ if(s[i-1] == s[i+1]){ x = 2; } else{ x = max(x,1); } } } cout << ans - x << endl; } return 0;}C1-贪心
题目
优素福给了你两个长度相同的二进制字符串 和 。
您可以执行以下任意操作:
- 在 中选择一个与 相等的子串 ,并替换为 ,反之亦然(即 或 )。
- 在 中选择一个等于 的子串,并将其替换为 ,反之亦然(即 或 )。
您的任务是确定是否可能用有限次的运算将字符串 转换为字符串 。
如果通过删除开头的几个(可能是零个或全部)字符和结尾的几个(可能是零个或全部)字符,可以从 得到 ,那么字符串 就是字符串 的子串。
贪心
共有000,001,010,011,100,101,110,111等8种状态,对于可操作的四种状态种,等同于将和自由交换,显然的操作不会改变索引的奇偶性,对于不可操作的其余四种状态可以发现0和1的奇偶性不会改变,那么我们可以无休止地交换奇数索引处的字符(想换多少次就换多少次),因此我们可以将它们重新排列成我们想要的任何排列,而与偶数索引处的字符无关。
因此,如果 中奇数位置上的元素与 中奇数位置上的元素的1(或0)个数相同,那么它们就可以匹配。同样的方法也适用于偶数位置。
#include<bits/stdc++.h>using namespace std;int main(){ int t; cin >> t; while(t--){ int n; cin >> n; string a,b; cin >> a >> b; int cnta[2] = {},cntb[2] = {}; for(int i = 0;i < n;i++){ cnta[i%2] += a[i] == '1'; cntb[i%2] += b[i] == '1'; } cout << (cnta[0] == cntb[0] && cnta[1] == cntb[1] ? "YES" : "NO") << endl; }}C2-贪心
题目
在C1的基础上求将a转化为b的最小操作次数,如果i无法转化输出-1
贪心
对于同一奇偶性组:
- 把
a中该组所有1的位置按顺序排列:posA[0], posA[1], ... - 把
b中该组所有1的位置按顺序排列:posB[0], posB[1], ... - 最优匹配就是按顺序一一对应
对于每个匹配对 (posA[i], posB[i]):
- 移动距离是
|posA[i] - posB[i]| / 2
#include<bits/stdc++.h>using namespace std;int main(){ int t; cin >> t; while(t--){ int n; cin >> n; string a,b; cin >> a >> b; long long ans = 0; bool ok = true; for(int k = 0;k < 2;k++){ vector<int>p1,p2; for(int i = k;i < n;i += 2){ if(a[i] == '1'){ p1.push_back(i); } if(b[i] == '1'){ p2.push_back(i); } }
if(p1.size() != p2.size()){ ok = false; break; } for(int i = 0;i < p1.size();i++){ ans += abs(p1[i] - p2[i]); }
}
if(!ok){ cout << -1 << endl; } else{ cout << ans/2 << endl; }
} return 0;}D-构造
题目
尤塞夫有一个由 个严格正整数组成的秘密数组 。
对于每个元素 来说,它的影子 是 中所有严格小于 的元素之和。形式上
给你一个阴影数组 。你的任务是重构一个由满足上述条件的严格正整数组成的逻辑上最小的有效数组 。如果不存在这样的数组,则输出 。
构造
给定影子数组 b,其中 b_i 等于数组 a 中所有严格小于 a_i 的元素之和。
我们需要构造字典序最小的正整数数组 a,若不存在则输出 -1。
-
将
a中所有不同值从小到大排序:对应出现次数为 。
-
对于值为 的元素,它的影子值等于:
这是严格小于它的所有元素之和。
-
因此,所有等于 的位置,其
b值必须相同,且等于 。不同
b值必须严格递增,且最小的b值一定是0(因为最小的 没有更小的元素)。 -
将
b中所有不同值排序:其中 ,且每个 的出现次数就是 。
-
由前缀和关系:
所以:
必须为正整数,并且必须满足 ()。
-
最后一组 没有后继约束,为了字典序最小,取:
-
如果所有条件满足,则根据原
b的顺序,将每个b_i映射到对应的 ,即为答案。否则输出
-1。
from collections import Counterfor _ in range(int(input())): n = int(input()) b = list(map(int, input().split())) cnt = Counter(b) val = sorted(cnt.keys()) if val[0] != 0: print(-1) continue m = len(val) if m == 1: print(" ".join(["1"] * n)) continue a = {} pre = 0 ok = True for i in range(m - 1): x = val[i] xn = val[i + 1] dif = xn - x if dif % cnt[x] != 0: ok = False break v = dif // cnt[x] if v <= pre: ok = False break a[x] = v pre = v if not ok: print(-1) continue xend = val[-1] a[xend] = pre + 1 ans = [str(a[x]) for x in b] print(" ".join(ans))文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!