Educational Codeforces Round 174 (Rated for Div. 2)
A. Was there an Array?
题意:一个长度为
如果
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n - 2);
for (int i = 0; i < n - 2; ++ i) {
std::cin >> a[i];
}
for (int i = 0; i + 2 < n - 2; ++ i) {
if (a[i] == 1 && a[i + 1] == 0 && a[i + 2] == 1) {
std::cout << "NO\n";
return;
}
}
std::cout << "YES\n";
}
B. Set of Strangers
题意:给你一个矩阵,你每次可以选择一些元素,使得它们的值都相同且没有两个元素相邻,然后把他们变成另一种元素,问让整个矩阵相同的最小操作数。
发现同一种颜色最多操作两次,如果这个颜色每个元素都不相邻,那么只需要一次就可以全部变,如果有相邻点,那么可以取
于是把每个元素的操作数存下来,排序后除最后一个不选,其他颜色的操作数都算上。
点击查看代码
void solve() {
int n, m;
std::cin >> n >> m;
std::vector a(n, std::vector<int>(m));
for (int i = 0; i < n; ++ i) {
for (int j = 0; j < m; ++ j) {
std::cin >> a[i][j];
-- a[i][j];
}
}
const int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
std::vector<int> cnt(n * m);
for (int i = 0; i < n; ++ i) {
for (int j = 0; j < m; ++ j) {
if (cnt[a[i][j]] < 2) {
cnt[a[i][j]] = 1;
for (int k = 0; k < 4; ++ k) {
int x = i + dx[k], y = j + dy[k];
if (x < 0 || x >= n || y < 0 || y >= m) {
continue;
}
if (a[i][j] == a[x][y]) {
cnt[a[i][j]] = 2;
}
}
}
}
}
std::vector<int> b;
for (int i = 0; i < n * m; ++ i) {
if (cnt[i]) {
b.push_back(cnt[i]);
}
}
std::sort(b.begin(), b.end());
int ans = 0;
for (int i = 0; i + 1 < b.size(); ++ i) {
ans += b[i];
}
std::cout << ans << "\n";
}
C. Beautiful Sequence
题意:给你一个数组,只有
预处理
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
std::vector<int> pre1(n + 1), suf2(n + 2), suf3(n + 2);
for (int i = 0; i < n; ++ i) {
pre1[i + 1] = pre1[i] + (a[i] == 1);
}
for (int i = n - 1; i >= 0; -- i) {
suf2[i + 1] = suf2[i + 2] + (a[i] == 2);
suf3[i + 1] = suf3[i + 2] + (a[i] == 3);
}
Z ans = 0, pre = 0;
for (int i = 1; i <= n; ++ i) {
if (a[i - 1] == 2) {
ans += (Z)pre1[i] * suf3[i] + pre / power<Z>(2, suf2[i]) * suf3[i];
pre += pre1[i] * power<Z>(2, suf2[i] - 1);
}
}
std::cout << ans << "\n";
}
D. Palindrome Shuffle
题意:给你一个字符串,你可以进行一次操作,重新排列一个区间,使得字符串是回文串,求区间最短长度。
记
否则我们可以二分往中间左边走几步和往中间右边走几步,看重排这个区间能否是回文串,
点击查看代码
void solve() {
std::string s;
std::cin >> s;
int n = s.size();
std::vector<std::array<int, 26>> sum(n + 1);
for (int i = 0; i < n; ++ i) {
sum[i + 1] = sum[i];
sum[i + 1][s[i] - 'a'] += 1;
}
int l = 0;
while (l < n / 2 && s[l] == s[n - 1 - l]) {
++ l;
}
if (l == n / 2) {
std::cout << 0 << "\n";
return;
}
int r = n / 2 - 1;
while (r > l && s[r] == s[n - 1 - r]) {
-- r;
}
bool flag = true;
++ l, ++ r;
for (int i = 0; i < 26; ++ i) {
if (sum[r][i] - sum[l - 1][i] != sum[n - l + 1][i] - sum[n - r][i]) {
flag = false;
break;
}
}
if (flag) {
std::cout << r - l + 1 << "\n";
} else {
auto check1 = [&](int k) -> bool {
std::array<int, 26> cnt{};
for (int i = 0; i < 26; ++ i) {
cnt[i] = sum[n / 2 + k][i] - sum[l - 1][i];
}
for (int i = (n - l + 1); i > n / 2 + k; -- i) {
if ( -- cnt[s[i - 1] - 'a'] < 0) {
return false;
}
}
for (int i = 0; i < 26; ++ i) {
if (cnt[i] & 1) {
return false;
}
}
return true;
};
int L = 1, R = (n - l + 1) - n / 2;
while (L < R) {
int mid = L + R >> 1;
if (check1(mid)) {
R = mid;
} else {
L = mid + 1;
}
}
int ans = L + n / 2 - l + 1;
auto check2 = [&](int k) -> bool {
std::array<int, 26> cnt{};
for (int i = 0; i < 26; ++ i) {
cnt[i] = sum[n - l + 1][i] - sum[n / 2 - k][i];
}
for (int i = l; i < n / 2 - k + 1; ++ i) {
if ( -- cnt[s[i - 1] - 'a'] < 0) {
return false;
}
}
for (int i = 0; i < 26; ++ i) {
if (cnt[i] & 1) {
return false;
}
}
return true;
};
L = 1, R = n / 2 - l + 1;
while (L < R) {
int mid = L + R >> 1;
if (check2(mid)) {
R = mid;
} else {
L = mid + 1;
}
}
ans = std::min(ans, L + (n - l + 1) - n / 2);
std::cout << ans << "\n";
}
}
E. A, B, AB and BA
题意:给你一个
赛后补题。
这题也是一个思维题,属于是找到思路后仔细想应该就能想出来做法的,但这题步骤比较多,导致评价为依托。我也是看了别人的题解。
因为我们没有
- 长度为偶数以
开头: - 长度为奇数以
开头: - 长度为偶数以
开头: - 长度为奇数以
开头:
一个显然的贪心是,我们应该先用
一个需要注意的地方是,按照上面顺序处理的过程中,我们应该先处理长度小的,因为假设我们用
点击查看代码
void solve() {
std::string s;
std::cin >> s;
int n = s.size();
int cnt1[2]{}, cnt2[2]{};
std::cin >> cnt1[0] >> cnt1[1] >> cnt2[0] >> cnt2[1];
std::vector<int> even[2], odd[2];
for (int l = 0, r = 1; r <= n; ++ r) {
if (r == n || s[r] == s[r - 1]) {
if (r - l & 1) {
odd[s[l] - 'A'].push_back(r - l);
} else {
even[s[l] - 'A'].push_back(r - l);
}
l = r;
}
}
for (int i = 0; i < 2; ++ i) {
std::sort(odd[i].begin(), odd[i].end(), std::greater<int>());
std::sort(even[i].begin(), even[i].end(), std::greater<int>());
}
for (int i = 0; i < 2; ++ i) {
while (cnt2[i] && even[i].size()) {
int m = even[i].back(); even[i].pop_back();
int k = std::min(m / 2, cnt2[i]);
cnt2[i] -= k; m -= k * 2;
if (m) {
even[i].push_back(m);
}
}
}
for (int i = 0; i < 2; ++ i) {
while (cnt2[i ^ 1] && even[i].size()) {
int m = even[i].back(); even[i].pop_back();
int k = std::min(m / 2 - 1, cnt2[i ^ 1]);
cnt2[i ^ 1] -= k; m -= k * 2;
if (m) {
cnt1[i] -= m / 2;
cnt1[i ^ 1] -= m / 2;
}
}
}
for (int i = 0; i < 2; ++ i) {
for (int j = 0; j < 2; ++ j) {
while (cnt2[i] && odd[j].size()) {
int m = odd[j].back(); odd[j].pop_back();
int k = std::min(cnt2[i], m / 2);
cnt2[i] -= k; m -= k * 2;
if (m > 1) {
odd[j].push_back(m);
} else {
cnt1[j] -= 1;
}
}
}
}
for (int i = 0; i < 2; ++ i) {
while (even[i].size()) {
int m = even[i].back(); even[i].pop_back();
cnt1[0] -= m / 2;
cnt1[1] -= m / 2;
}
while (odd[i].size()) {
int m = odd[i].back(); odd[i].pop_back();
cnt1[i] -= m / 2 + 1;
cnt1[i ^ 1] -= m / 2;
}
}
if (cnt1[0] < 0 || cnt1[1] < 0) {
std::cout << "NO\n";
} else {
std::cout << "YES\n";
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析