
壁纸链接
题目链接:https://atcoder.jp/contests/abc469/tasks
A - Train Car
将位置从前往后编号为,再从后往前编号为。因此前端第个位置对应的反向编号为,直接输出即可。
void solved(){ int n, k; cin >> n >> k; cout << n - k + 1 << endl;}B - Isolated Seats
直接遍历字符串,判断每个位置是否为空位,并且所有存在的相邻位置也都是空位。对于中间位置,需要满足;对于左右端点,只需要额外判断唯一存在的相邻位置。
当时不存在相邻位置,所以唯一字符为时答案为,否则为,需要单独处理。整体只需要一次线性遍历,时间复杂度为。
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
关键是分析当前持有的数量如何变化。每次操作会先消耗一个,再取得下一个字符:如果新字符为,持有的数量不变;如果为,持有的数量减一。因此,初始前缀中有多少个,后续就可以经过多少个,操作会在取得最后一个可经过的后停止。
对于前个字符,记其中和的数量分别为。如果,没有可用于继续操作的,答案就是。否则停止时到达的在整个字符串中的序号为
,也就是整个字符串中第个的位置。如果字符串中不存在第个,说明可以一直操作到序列末尾,答案为。
我们预处理所有出现的位置,然后从左往右维护前缀中的数量,每个都可以在时间内得到答案。总时间复杂度为,空间复杂度为。
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
将每名选手看作一个点,每场决赛的两名选手看作一条无向边。题目要求统计二元点集,使每条边都至少有一个端点属于这个集合,也就是统计大小为的点覆盖。
设第一条边为。任何合法点覆盖都必须包含中的至少一个,因此只需要分别固定和,再统计另一个点的选择数量。
对于一个固定的,我们找到第一条不与相连的边。为了覆盖这条边,只能是或,分别枚举这两个候选点,再遍历所有边检查能否将其覆盖。如果不存在不与相连的边,说明单独就能覆盖全部边,此时除以外的任意点都可以作为,方案数为。
和的结果相加时,点集可能被计算两次。因此再检查本身是否覆盖所有边,如果满足条件就将答案减一。每次检查只需要线性扫描边集,整体时间复杂度为,空间复杂度为。
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 998244353typedef 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;}