744 字
2 分钟
Atcoder_Beginner_Contest_458(A~D题)
2026-05-16
统计加载中...

这期abcabc跨度巨大,后面EFE-F题的NTTNTTACAC自动机超出我目前的水平了,所以就不补了。
题目链接:https://atcoder.jp/contests/abc458/tasks

A - Chompers#

只输出字符串中间的答案部分即可。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define endl '\n'
#define mod 998244353
typedef pair<int, int> pii;
void solved() {
string s;
int n;
cin >> s >> n;
for (int i = 0; i < s.size(); i++){
if(i >= n && i < (int)s.size() - n){
cout << s[i];
}
}
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
while(_--){
solved();
}
return 0;
}

B - Count Adjacent Cells#

我们先让数组的值初始化为全11,然后每次通过方向数组累加周围四格的值就是答案了。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define endl '\n'
#define mod 998244353
typedef pair<int, int> pii;
int a[60][60];
int tx[5] = {0, 0, 0, 1, -1};
int ty[5] = {0, 1, -1, 0, 0};
void solved() {
int n, m;
cin >> n >> m;
memset(a, 1, sizeof(a));
for(int i = 1; i <= n;i++)
for(int j = 1; j <= m;j++)
a[i][j] = 1;
for(int i = 1; i <= n;i++){
for (int j = 1; j <= m;j++){
int cnt = 0;
for(int k = 1; k <= 4;k++){
int x = i + tx[k];
int y = j + ty[k];
if(a[x][y] == 1){
cnt++;
}
}
cout << cnt << " ";
}
cout << endl;
}
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
while(_--){
solved();
}
return 0;
}

C - C Stands for Center#

这题我们先记录下所有CC的字符的位置,思路是每次我们都以当前的CC字符的位置为中心,左右分别取一个字符。如果可以取到,cntcnt就加一,然后继续左右分别取一个,只要左右有一方取不到就停。这里我们直接取左右端离中心CC距离较小的一段直接计入cntcnt即可。如果没有CC字符出现就输出00

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define endl '\n'
#define mod 998244353
typedef pair<int, int> pii;
void solved() {
vector<int> pos;
string s;
cin >> s;
for(int i = 0; i < (int)s.size();i++){
if(s[i] == 'C'){
pos.push_back(i);
}
}
if(pos.size() == 0){
cout << 0 << endl;
return;
}
ll cnt = (int)pos.size();
for(auto it : pos){
it++;
cnt += min(it - 1, (int)s.size() - it);
}
cout << cnt << endl;
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
while(_--){
solved();
}
return 0;
}

D - Chalkboard#

这题我们看到需要在每次查询都输出这个不断更新的序列的中位数。但这里要注意的是,如果我们每次都进行遍历操作的话就会超时。所以我们需要优化我们的思路。
这里其实很容易想到使用优先队列进行快速排序的操作来方便我们查询。但问题是优先队列只能看到队顶的元素,并且也只能操作队顶。看起来似乎是无法查找中位数的。不过我们可以利用一个双堆来查找中位数。
我们开一个最大堆和最小堆,它们的堆顶分别是堆里的最大值和最小值。现在我们让最大堆里面整个序列的偏小的下半部分,最小堆里面是偏大的上半部分。那么我们就可以让最大堆和最小堆的堆顶分别存放中间的两个数了。如果是偶数的话我们就取两边堆顶的值除以22。奇数时我们就取元素更多的那一边的堆顶即可。
现在我们看如何构造这样的两个堆。我们先将一个元素压入最大堆,然后再弹出最大堆的堆顶,将它加到最小堆里。此时如果最大堆的元素个数小于了最小堆里的元素个数,我们就重新将它移回最大堆。我们不难发现,这样的操作每次都将相对较大的数放进了最小堆,把较小的数留在了最大堆,从而可以保证每次中位数都在堆顶,从而满足要求。
这题每次查询时都是压入堆中的序列和都是奇数,所以根据我们的构造,每次查询时输出最大堆的堆顶就是中位数了。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define endl '\n'
#define mod 998244353
typedef pair<int, int> pii;
priority_queue<int, vector<int>, greater<int>> min_pq;
priority_queue<int> max_pq;
void add(int x){
max_pq.push(x);
min_pq.push(max_pq.top());
max_pq.pop();
if(max_pq.size() < min_pq.size()){
max_pq.push(min_pq.top());
min_pq.pop();
}
}
void solved() {
int x, q;
cin >> x >> q;
max_pq.push(x);
while(q--){
int a, b;
cin >> a >> b;
add(a), add(b);
cout << max_pq.top() << endl;
}
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
while(_--){
solved();
}
return 0;
}
分享

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

Atcoder_Beginner_Contest_458(A~D题)
https://mkrari.cn/posts/abc_458/
作者
Mkrari
发布于
2026-05-16
许可协议
CC BY-NC-SA 4.0