七海ノ心象素描

所有的为时已晚都是恰逢其时

Nanami^2 avatar

Author

Nanami^2

大一学生 | 不是很聪明的样子

Telegram

我的频道

不定期推送灵感笔记

t.me/kisanami_blog
联系方式
QQ 群
1072614878
发送邮件

AtCoder Beginner Contest 447

个人题解

Nanami^2
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)的都提取出来,对齐一下下标,并求出 cs,ctcs, ct 为两个串各自A的数量。设 R(i,0/1)R(i, 0/1) 为两个串第 iiA的数量,显然只能保留 2min(R(i,0),R(i,1))2\min\big(R(i,0), R(i, 1) \big) 个,最后注意一下结尾的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的数量 cacaAB的数量 cabcab,遇到一个A时增加 caca,遇到B时,如果 ca>0ca > 0,就增加 cabcabcaca 减少 11。遇到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

考虑二进制的性质,我们知道如果你删掉了边 ii,那么代价大于删掉 [1,i)[1, i) 中的所有边,所以应该能删则删。

保留恰好两个连通块,贪心选边,联想到 Kruskal 算法的过程。因为要保证连通块恰好为 22,所以还要有一个减少连通块的过程,也就是一些权值很小的边是必须保留的,这与我们上述的策略产生了冲突。

如何解决?转化一下就是我们尽可能不要保留编号大的边,于是我们按照边权(编号)递减排序,贪心用权值大的边减少连通块即可。

如果当前连通块数量大于 22,那么我们贪心保留边并合并,否则删掉这条边

F

赛时没有做出来。

觉得这篇文章怎么样?

点个赞,让更多人看到!

分享这篇文章

知识因分享而增值

分类

比赛
AtCoder

标签

DP
图论
最小生成树
计数
树形DP

版权声明:本文作者为 Nanami^2,首发于nanami7.top

遵循 CC BY-NC-SA 4.0 许可协议。转载请注明出处!

评论区

本评论区由 EveSunMaple 自主开发