765 字
2 分钟
Atcoder_Beginner_Contest_469(A~D题)
2026-08-02
浏览量 81 · 访客 3

壁纸链接
题目链接:https://atcoder.jp/contests/abc469/tasks

A - Train Car#

将位置从前往后编号为1,2,,N1,2,\ldots,N,再从后往前编号为N,N1,,1N,N-1,\ldots,1。因此前端第KK个位置对应的反向编号为NK+1N-K+1,直接输出即可。

void solved(){
int n, k; cin >> n >> k;
cout << n - k + 1 << endl;
}

B - Isolated Seats#

直接遍历字符串,判断每个位置是否为空位,并且所有存在的相邻位置也都是空位。对于中间位置ii,需要满足Si1=Si=Si+1=xS_{i-1}=S_i=S_{i+1}=x;对于左右端点,只需要额外判断唯一存在的相邻位置。
N=1N=1时不存在相邻位置,所以唯一字符为xx时答案为11,否则为00,需要单独处理。整体只需要一次线性遍历,时间复杂度为O(N)O(N)

void solved(){
int n; cin >> n;
int cnt = 0;
string s; cin >> s;
if(n == 1 && s[0] == 'x') {cout << 1 << endl; return;}
else if(n == 1 && s[0] == 'o') {cout << 0 << endl; return;}
for(int i = 0; i < (int)s.size();i++){
if(i == 0 && s[i] == 'x' && s[i + 1] == 'x')
cnt++;
else if(i == (int)s.size() - 1 && s[i] == 'x' && s[i - 1] == 'x')
cnt++;
else if(i > 0 && s[i - 1] == 'x' && s[i] == 'x' && s[i + 1] == 'x')
cnt++;
}
cout << cnt << endl;
}

C - Cantrip#

关键是分析当前持有的oo数量如何变化。每次操作会先消耗一个oo,再取得下一个字符:如果新字符为oo,持有的oo数量不变;如果为xx,持有的oo数量减一。因此,初始前缀中有多少个oo,后续就可以经过多少个xx,操作会在取得最后一个可经过的xx后停止。
对于前ii个字符,记其中ooxx的数量分别为o_cnt,x_cnto\_cnt,x\_cnt。如果o_cnt=0o\_cnt=0,没有可用于继续操作的oo,答案就是ii。否则停止时到达的xx在整个字符串中的序号为 x_cnt+o_cnt=ix\_cnt+o\_cnt=i,也就是整个字符串中第iixx的位置。如果字符串中不存在第iixx,说明可以一直操作到序列末尾,答案为NN
我们预处理所有xx出现的位置,然后从左往右维护前缀中o,xo,x的数量,每个ii都可以在O(1)O(1)时间内得到答案。总时间复杂度为O(N)O(N),空间复杂度为O(N)O(N)

void solved(){
int n; cin >> n;
string s; cin >> s;
vector<int> x_pos;
for(int i = 0; i < n;i++){
if(s[i] == 'x')
x_pos.push_back(i + 1);
}
int total_x = (int)x_pos.size();
int o_cnt = 0, x_cnt = 0;
for(int i = 1; i <= n;i++){
char c = s[i - 1];
if(c == 'o') o_cnt++;
else x_cnt++;
if(!o_cnt) cout << i << endl;
else{
int index = x_cnt + o_cnt;
if(index <= total_x)
cout << x_pos[index - 1] << endl;
else cout << n << endl;
}
}
}

D - The Big Two#

将每名选手看作一个点,每场决赛的两名选手(Ai,Bi)(A_i,B_i)看作一条无向边。题目要求统计二元点集{x,y}\{x,y\},使每条边都至少有一个端点属于这个集合,也就是统计大小为22的点覆盖。
设第一条边为(u,v)(u,v)。任何合法点覆盖都必须包含u,vu,v中的至少一个,因此只需要分别固定x=ux=ux=vx=v,再统计另一个点yy的选择数量。
对于一个固定的xx,我们找到第一条不与xx相连的边(a,b)(a,b)。为了覆盖这条边,yy只能是aabb,分别枚举这两个候选点,再遍历所有边检查{x,y}\{x,y\}能否将其覆盖。如果不存在不与xx相连的边,说明xx单独就能覆盖全部边,此时除xx以外的任意点都可以作为yy,方案数为N1N-1
count_with(u)count\_with(u)count_with(v)count\_with(v)的结果相加时,点集{u,v}\{u,v\}可能被计算两次。因此再检查{u,v}\{u,v\}本身是否覆盖所有边,如果满足条件就将答案减一。每次检查只需要线性扫描边集,整体时间复杂度为O(M)O(M),空间复杂度为O(M)O(M)

void solved(){
int N, M; cin >> N >> M;
vector<pii> match(M);
for(auto &[a, b] : match){
cin >> a >> b;
}
auto count_with = [&](int x) -> int {
int first = -1;
for(int i = 0; i < M;i++){
int a = match[i].first, b = match[i].second;
if(a != x && b != x){
first = i;
break;
}
}
if(first == -1) return N - 1;
int cnt = 0;
int candicate[2] = {match[first].first, match[first].second};
for(int y : candicate){
bool ok = true;
for(auto [a, b] : match){
if(a != x && b != y && a != y && b != x){
ok = false;
break;
}
}
cnt += ok;
}
return cnt;
};
int u = match[0].first, v = match[0].second;
int ans = count_with(u) + count_with(v);
bool first_pair_yes = true;
for(int i = 0; i < M;i++){
int a = match[i].first, b = match[i].second;
if(u != a && u != b && v != a && v != b){
first_pair_yes = false;
break;
}
}
ans -= first_pair_yes;
cout << ans << endl;
}

模板:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
#define endl '\n'
#define mod 998244353
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
ll fast_pow(ll a, ll b, ll MOD) {
ll ans = 1;
while (b) {
if (b & 1) ans = (ans * a) % MOD;
b >>= 1;
a = (a * a) % MOD;
}
return ans;
}
vector<ll> get_inverse(ll n, ll MOD){
vector<ll> inverse(n + 1);
inverse[1] = 1;
for(ll i = 2; i <= n;i++){
inverse[i] = MOD - (MOD / i) * (inverse[MOD % i]) % MOD;
}
return inverse;
}
void solved() {
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
//cin >> _;
while (_--) {
solved();
}
return 0;
}
分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Atcoder_Beginner_Contest_469(A~D题)
https://mkrari.cn/posts/abc_469/
作者
Mkrari
发布于
2026-08-02
许可协议
CC BY-NC-SA 4.0