AtCoder Beginner Contest 447
个人题解
Nanami^2 Even in the rain.
2026年02月28日
预计阅读 9 分钟
1894 字
A
#include<bits/stdc++.h>#include<concepts>using namespace std;typedef long long ll;typedef unsigned long long ull;typedef pair<int, int> PII;#define MP make_pair#define fi first#define se second#define pb push_back#define eb emplace_back#define SET(a, b) memset(a, b, sizeof(a))#define CPY(a, b) memcpy(a, b, sizeof(b))#define rep(i, j, k) for(int i = (j); i <= (k); ++i)#define per(i, j, k) for(int i = (j); i >= (k); --i)struct FastIO { static const int MAXSIZE = 1 << 20; char buf[MAXSIZE], *p1, *p2; char pbuf[MAXSIZE], *pp;
FastIO() : p1(buf), p2(buf), pp(pbuf) {} ~FastIO() { flush(); }
void flush() { if (pp > pbuf) { fwrite(pbuf, 1, pp - pbuf, stdout); pp = pbuf; } }
char gc() { if (p1 == p2) { p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin); if (p1 == p2) return EOF; } return *p1++; }
void pc(char c) { if (pp - pbuf == MAXSIZE) flush(); *pp++ = c; } template <typename T> void read(T &x) { x = 0; bool neg = false; char ch = gc(); while (!isdigit(ch) && ch != EOF) { if (ch == '-') neg = true; ch = gc(); } if (ch == EOF) return; while (isdigit(ch)) { x = x * 10 + (ch - '0'); ch = gc(); } if (neg) x = -x; }
template <typename T> void write(T x) { if (x < 0) { pc('-'); x = -x; } static int sta[45]; int top = 0; do { sta[top++] = x % 10; x /= 10; } while (x); while (top) pc(sta[--top] + '0'); }
template <typename T> void write(T x, char lastChar) { write(x); pc(lastChar); }} io;signed main() { // ios::sync_with_stdio(false); // cin.tie(nullptr); int n = 0, m = 0; io.read(n); io.read(m); if(n >= (m * 2 - 1)) puts("Yes"); else puts("No"); return 0;}B
#include<bits/stdc++.h>#include<concepts>using namespace std;typedef long long ll;typedef unsigned long long ull;typedef pair<int, int> PII;#define MP make_pair#define fi first#define se second#define pb push_back#define eb emplace_back#define SET(a, b) memset(a, b, sizeof(a))#define CPY(a, b) memcpy(a, b, sizeof(b))#define rep(i, j, k) for(int i = (j); i <= (k); ++i)#define per(i, j, k) for(int i = (j); i >= (k); --i)struct FastIO { static const int MAXSIZE = 1 << 20; char buf[MAXSIZE], *p1, *p2; char pbuf[MAXSIZE], *pp;
FastIO() : p1(buf), p2(buf), pp(pbuf) {} ~FastIO() { flush(); }
void flush() { if (pp > pbuf) { fwrite(pbuf, 1, pp - pbuf, stdout); pp = pbuf; } }
char gc() { if (p1 == p2) { p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin); if (p1 == p2) return EOF; } return *p1++; }
void pc(char c) { if (pp - pbuf == MAXSIZE) flush(); *pp++ = c; } template <typename T> void read(T &x) { x = 0; bool neg = false; char ch = gc(); while (!isdigit(ch) && ch != EOF) { if (ch == '-') neg = true; ch = gc(); } if (ch == EOF) return; while (isdigit(ch)) { x = x * 10 + (ch - '0'); ch = gc(); } if (neg) x = -x; }
template <typename T> void write(T x) { if (x < 0) { pc('-'); x = -x; } static int sta[45]; int top = 0; do { sta[top++] = x % 10; x /= 10; } while (x); while (top) pc(sta[--top] + '0'); }
template <typename T> void write(T x, char lastChar) { write(x); pc(lastChar); }} io;string s;int c[100];signed main() { // ios::sync_with_stdio(false); // cin.tie(nullptr); cin >> s; int mx = 0; for(auto x : s) { c[x - 'a']++; mx = max(mx, c[x - 'a']); } for(auto x : s) if(c[x - 'a'] < mx) { cout << x; } cout << endl; return 0;}C
显然我们把两个串里所有的A去掉,然后如果此时不相同直接无解了。
然后我们分别把两个串里所有的A连续段(包括长度为 0)的都提取出来,对齐一下下标,并求出 为两个串各自A的数量。设 为两个串第 段A的数量,显然只能保留 个,最后注意一下结尾的A连续段即可。
#include<bits/stdc++.h>#include<concepts>using namespace std;typedef long long ll;typedef unsigned long long ull;typedef pair<int, int> PII;#define MP make_pair#define fi first#define se second#define pb push_back#define eb emplace_back#define SET(a, b) memset(a, b, sizeof(a))#define CPY(a, b) memcpy(a, b, sizeof(b))#define rep(i, j, k) for(int i = (j); i <= (k); ++i)#define per(i, j, k) for(int i = (j); i >= (k); --i)struct FastIO { static const int MAXSIZE = 1 << 20; char buf[MAXSIZE], *p1, *p2; char pbuf[MAXSIZE], *pp;
FastIO() : p1(buf), p2(buf), pp(pbuf) {} ~FastIO() { flush(); }
void flush() { if (pp > pbuf) { fwrite(pbuf, 1, pp - pbuf, stdout); pp = pbuf; } }
char gc() { if (p1 == p2) { p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin); if (p1 == p2) return EOF; } return *p1++; }
void pc(char c) { if (pp - pbuf == MAXSIZE) flush(); *pp++ = c; } template <typename T> void read(T &x) { x = 0; bool neg = false; char ch = gc(); while (!isdigit(ch) && ch != EOF) { if (ch == '-') neg = true; ch = gc(); } if (ch == EOF) return; while (isdigit(ch)) { x = x * 10 + (ch - '0'); ch = gc(); } if (neg) x = -x; }
template <typename T> void write(T x) { if (x < 0) { pc('-'); x = -x; } static int sta[45]; int top = 0; do { sta[top++] = x % 10; x /= 10; } while (x); while (top) pc(sta[--top] + '0'); }
template <typename T> void write(T x, char lastChar) { write(x); pc(lastChar); }} io;const int N = 3e5 + 5;string s, t;string s0, t0;int R[N][2];signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> s >> t; int cs = 0, ct = 0; for(auto x : s) { if(x != 'A') { s0 += x; } else cs++; } for(auto x : t) { if(x != 'A') { t0 += x; } else ct++; } if(s == t) { cout << 0 << endl; return 0; } // cout << s0 << endl; // cout << t0 << endl; if(s0 != t0) { cout << -1 << endl; return 0; }
int m = s0.size(), lst = 0, p = 0; for(int i = 0; i < s.size(); i++) { if(s[i] == 'A' && i != 0 && s[i - 1] != 'A') lst = i; else if(s[i] != 'A') R[++p][0] = i - lst, lst = i + 1; } lst = 0; p = 0; for(int i = 0; i < t.size(); i++) { if(t[i] == 'A' && i != 0 && t[i - 1] != 'A') lst = i; else if(t[i] != 'A') R[++p][1] = i - lst, lst = i + 1; } int res = 0; int c1 = 0, c2 = 0; for(int i = s.size() - 1; ~i; i--) { if(s[i] == 'A') c1++; else break; } for(int i = t.size() - 1; ~i; i--) { if(t[i] == 'A') c2++; else break; } for(int i = 1; i <= m; i++) { res += 2 * min(R[i][0], R[i][1]); // cout << R[i][0] << " " << R[i][1] << endl; } cout << cs + ct - res - 2 * min(c1, c2) << endl; return 0;}D
考虑一个策略:我们从左往右扫到第一个A,再往右找到第一个B,再找到第一个C,然后匹配之。
这样一定是最优秀的,因为每个C匹配尽可能靠前的AB最优,每个B匹配最靠前的A最优。
不过这样不是很好写,需要处理挺多细节。
考虑一个经典 Trick,我们直接维护当前位置A的数量 ,AB的数量 ,遇到一个A时增加 ,遇到B时,如果 ,就增加 , 减少 。遇到C时匹配掉一个AB即可。
#include<bits/stdc++.h>using namespace std;typedef long long ll;typedef unsigned long long ull;typedef pair<int, int> PII;#define MP make_pair#define fi first#define se second#define pb push_back#define eb emplace_back#define SET(a, b) memset(a, b, sizeof(a))#define CPY(a, b) memcpy(a, b, sizeof(b))#define rep(i, j, k) for(int i = (j); i <= (k); ++i)#define per(i, j, k) for(int i = (j); i >= (k); --i)struct FastIO { static const int MAXSIZE = 1 << 20; char buf[MAXSIZE], *p1, *p2; char pbuf[MAXSIZE], *pp;
FastIO() : p1(buf), p2(buf), pp(pbuf) {} ~FastIO() { flush(); }
void flush() { if (pp > pbuf) { fwrite(pbuf, 1, pp - pbuf, stdout); pp = pbuf; } }
char gc() { if (p1 == p2) { p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin); if (p1 == p2) return EOF; } return *p1++; }
void pc(char c) { if (pp - pbuf == MAXSIZE) flush(); *pp++ = c; } template <typename T> void read(T &x) { x = 0; bool neg = false; char ch = gc(); while (!isdigit(ch) && ch != EOF) { if (ch == '-') neg = true; ch = gc(); } if (ch == EOF) return; while (isdigit(ch)) { x = x * 10 + (ch - '0'); ch = gc(); } if (neg) x = -x; }
template <typename T> void write(T x) { if (x < 0) { pc('-'); x = -x; } static int sta[45]; int top = 0; do { sta[top++] = x % 10; x /= 10; } while (x); while (top) pc(sta[--top] + '0'); }
template <typename T> void write(T x, char lastChar) { write(x); pc(lastChar); }} io;const int N = 1e6 + 5;int n, a[N][3];string s;signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> s; int ca = 0, cab = 0, ans = 0;
for(auto x : s) { if(x == 'A') { ca++; } else if(x == 'B') { if(ca > 0) { ca--; cab++; } } else if (x == 'C') { if (cab > 0) { cab--; ans++; } } } cout << ans << endl; return 0;}E
考虑二进制的性质,我们知道如果你删掉了边 ,那么代价大于删掉 中的所有边,所以应该能删则删。
保留恰好两个连通块,贪心选边,联想到 Kruskal 算法的过程。因为要保证连通块恰好为 ,所以还要有一个减少连通块的过程,也就是一些权值很小的边是必须保留的,这与我们上述的策略产生了冲突。
如何解决?转化一下就是我们尽可能不要保留编号大的边,于是我们按照边权(编号)递减排序,贪心用权值大的边减少连通块即可。
如果当前连通块数量大于 ,那么我们贪心保留边并合并,否则删掉这条边
F
赛时没有做出来。
觉得这篇文章怎么样?
点个赞,让更多人看到!

评论区