Educational Codeforces Round 75 (Rated for Div. 2)
比赛链接:https://codeforces.com/contest/1251
A - Broken Keyboard
题意
键盘的有些字母键是坏的,按一下会输入两个字母,正常的字母键一次只会输入一个字母,给出一段输入序列,判断哪些字母键是正常的。
题解
连续出现奇数次的字母一定是正常的。
代码
#include <bits/stdc++.h> using namespace std; void solve() { string s; cin >> s; set<char> st; for (int i = 0; i < s.size(); ) { int j = i + 1; while (j < s.size() and s[j] == s[i]) ++j; if ((j - i) % 2 == 1) st.insert(s[i]); i = j; } for (char c : st) cout << c; cout << "\n"; } int main() { int t; cin >> t; while (t--) solve(); }
B - Binary Palindromes
题意
$n$ 个 $01$ 串间不同位置的字符可以自由交换,计算最多可以形成多少个回文串。
题解
有一个很神奇的特性就是,如果有奇数长度的串,所有字符串都可以变为回文串。
如果没有的话,对于偶数串来说,如果 $0$ 和 $1$ 都出现奇数次是不可以组成回文串的,但是这种串可以两两结合交换为回文串,所以需要记录是否有奇数长的串,以及不回文的偶数长的串的个数。
代码
#include <bits/stdc++.h> using namespace std; void solve() { int n; cin >> n; bool len_odd = false; int cnt = 0; for (int i = 0; i < n; i++) { string s; cin >> s; if (s.size() % 2) len_odd = true; else { int cnt_0 = count(s.begin(), s.end(), '0'); int cnt_1 = count(s.begin(), s.end(), '1'); if (cnt_0 % 2 and cnt_1 % 2) ++cnt; } } cout << ((len_odd or cnt % 2 == 0) ? n : n - 1) << "\n"; } int main() { int t; cin >> t; while (t--) solve(); }
C - Minimize The Integer
题意
有一个数字串,相邻字符如果奇偶性不同可以相互交换,问这个数字串最小的值为多少。
题解
对于单独的奇数和偶数来说,它们的相对位置是不变的,所以依次记录奇数和偶数,每次取较小值即可。
代码
#include <bits/stdc++.h> using namespace std; void solve() { string s; cin >> s; vector<char> odd, even; for (char c : s) if ((c - '0') % 2 == 1) odd.push_back(c); else even.push_back(c); int i = 0, j = 0; while (true) { if (i == odd.size()) { while (j < even.size()) cout << even[j++]; break; } if (j == even.size()) { while (i < odd.size()) cout << odd[i++]; break; } cout << (odd[i] < even[j] ? odd[i++] : even[j++]); } cout << "\n"; } int main() { int t; cin >> t; while (t--) solve(); }
D - Salary Changing
题意
你有 $n$ 个员工,打算给他们一共发 $s$ 元的薪资,每个员工能接受的薪资范围在 $[l_i,r_i]$ 之间,计算所有薪资中的中位数的最大值。
题解
二分中位数 $mid$,
- 如果一个员工的 $r_i<mid$,那么只需给他发 $l_i$
- 如果一个员工的 $l_i≥mid$,那么也只需给他发 $l_i$
- 其余员工一定满足 $l_i < mid ≤ r_i$, 给 $l_i$ 较大的几个发 $mid$,其余的仍发 $l_i$ 即可
需要注意后两个人数至少应为总人数的一半以上才能满足 $mid$ 为所有薪资中的中位数。
代码
#include <bits/stdc++.h> using ll = long long; using namespace std; const int INF = 1e9 + 100; const int N = 2e5 + 100; ll n, s; pair<int, int> a[N]; bool ok(ll mid) { ll tot = s; vector<int> v; int cnt = 0; for (int i = 0; i < n; i++) { if (a[i].second < mid) tot -= a[i].first; else if (a[i].first >= mid) tot -= a[i].first, ++cnt; else v.push_back(a[i].first); } int half = (n + 1) / 2; if (cnt + v.size() < half) return false; sort(v.rbegin(), v.rend()); int need = max(0, half - cnt); tot -= need * mid + accumulate(v.begin() + need, v.end(), 0LL); return tot >= 0; } void solve() { cin >> n >> s; for (int i = 0; i < n; i++) cin >> a[i].first >> a[i].second; int l = 0, r = INF; int ans = 0; while (l <= r) { int mid = (l + r) / 2; if (ok(mid)) { ans = mid; l = mid + 1; } else r = mid - 1; } cout << ans << "\n"; } int main() { int t; cin >> t; while (t--) solve(); }
参考了 ~Lanly~ 的博客 ~

浙公网安备 33010602011771号