ABC398比赛报告
前言
- Rank4459(30%)
- 1075pts
- AC A B C D
题目分析
A - Doors in the Center
问题描述
找到一个长度为N的字符串,满足以下所有条件:
- 每个字符只能是
-
或=
。 - 它是一个回文字符串。
- 它恰好包含一个或两个
=
,如果包含两个=
,它们必须相邻。
这样的字符串是唯一的。
首先,我们分两种情况,长度为奇数,长度为偶数,观察样例一可以得到:
i = n / 2 : =
i = (n + 2) / 2 : =
else : -
奇数更简单,那么我们可以实现以下代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n';
#define fst ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int N = 1e6 + 10, M = 2e6 + 10;
int n;
signed main()
{fst;cin >> n;int maxn = n;if(maxn % 2 != 0){for(int i = 1;i <= maxn;i++){if(i == (maxn + 1)/2){cout << "=";}else{cout << "-";}}}else{for(int i = 1;i <= maxn;i++){if(i == (maxn / 2) || i == (maxn + 2) / 2){cout << "=";}else{cout << "-";}}}cout << endl;return 0;
}
B - Full House 3
问题描述
我们有七张卡片。第 i 张卡片(i=1... 7)上写着一个整数 Ai。
确定是否有可能从中选择五张,使得所选的卡片形成一个“同花顺”。
一组五张卡片被称为“同花顺”,当且仅当以下条件满足:
- 对于不同的整数 x 和 y,存在三张标有 x 的卡片和两张标有 y 的卡片。
那么我们读题后思路是这样的:
- 建立一个类似于vis的数组存储出现次数
- 给这个数组排序
- 判断是否有3或2同时存在
- 给出输出
有了以上思路,我们代码实现是这样的:
#include <bits/stdc++.h>
using namespace std;
int main() {int cnt[14] = {0};for (int i = 0; i < 7; ++i) {int a;cin >> a;cnt[a]++;}for (int x = 1; x <= 13; ++x) {if (cnt[x] >= 3) {for (int y = 1; y <= 13; ++y) {if (y == x) continue;if (cnt[y] >= 2) {cout << "Yes" << endl;return 0;}}}}cout << "No" << endl;return 0;
}
C - Uniqueness
问题描述
共有 N 人,编号为 1 到 N。第 i 个人拥有一个整数Ai。
在满足条件“除自己外的其他 N-1 个人没有与自己相同的整数”的人群中,找到拥有最大整数的那个人,并输出该人的编号。
若无人满足该条件,则输出这一事实。
思路:
- 由于题目中会给出每个人的号码,但是我们要找不重复的,所以我们为了方便需要新建一个结构体去存储这两个数据
- 然后我们根据数值的大小排序
- 通过cur记录一个中间值,最终用maxn存储答案
- 输出即可
以下是代码实现
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n';
#define fst ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int N = 1e6 + 10, M = 2e6 + 10;
const int INF = 0x3f3f3f3f3f3f3f3f3f;
const int P = 998254332;
struct el
{int val;int ind;
};
int n;
bool cmp(el x, el y)
{return x.val < y.val;
}
signed main()
{fst;cin >> n;vector<el> ele(n);for (int i = 0; i < n; ++i){cin >> ele[i].val;ele[i].ind = i;}sort(ele.begin(), ele.end(), cmp);int maxn = -INF;int res = -INF;int i = 0;while (i < n) {int cur = ele[i].val;int j = i;while (j < n && ele[j].val == cur) {j++;}int cnt = j - i;if (cnt == 1) {if (cur > maxn || (cur == maxn && ele[i].ind < res)){maxn = cur;res = ele[i].ind;}}i = j;}if (maxn == -INF){cout << -1 << endl;} else {cout << res + 1 << endl;}return 0;
}
D - Bonfire
问题说明
存在一个无限大的二维网格,营火位于坐标 (0,0)。
在时间 $t=0$ 时,仅存在一个烟点,位于单元格 (0,0) 处。
你将得到一个长度为 N 的字符串 S,内容由 N
、W
、S
、E
组成。在时间 t=1,2...,N 时,按照以下步骤进行:
- 风吹动,当前时刻存在的烟点会按照以下方式移动:
- 若 S 的第 t 个字符为
N
,则单元格 (r,c) 处的烟点移动到 (r-1,c)。 - 若为
W
,则移动到 (r,c-1)。 - 若为
S
,则移动到 (r+1,c)。 - 若为
E
,则移动到 (r,c+1)。
- 若 S 的第 t 个字符为
- 若单元格 $(0,0)$ 无烟点,则在此处生成新的烟点。
Takahashi 站在单元格 (R,C) 处。
对于 1 - N 中的每一个整数,判断在时间 t+0.5 时,单元格 (R,C) 处是否存在烟点,并根据要求的格式输出结果。
为了解决这个问题,我们需要在给定一系列风向的情况下,在每个时间步长t+0.5确定特定单元(R,C)是否存在烟雾。该解决方案涉及模拟在原点(0,0)处产生的烟雾的运动,并随时间跟踪其位置。
- 思路
1.前缀和数组:计算风向引起的行和列位移的前缀和。这有助于快速确定从任何开始时间到任何结束时间的累积位移。
2.哈希图跟踪:使用哈希图跟踪不同时间产生的烟雾的位置。这允许有效的查找,以检查从开始时间到当前时间的累积位移是否与目标坐标(R,C)匹配。
3.烟雾产生模拟:跟踪最近产生的烟雾的当前位置。如果将此烟雾移出原点导致生成新烟雾,请将当前位置更新到原点并记录生成时间。
有了以上思路,我们代码实现如下
#include <bits/stdc++.h>
using namespace std;struct pair_hash {template <class T1, class T2>size_t operator () (const pair<T1, T2> &p) const {auto h1 = hash<T1>{}(p.first);auto h2 = hash<T2>{}(p.second);return h1 ^ (h2 << 1);}
};int main() {int N, R, C;string S;cin >> N >> R >> C >> S;vector<int> dr(N + 1, 0), dc(N + 1, 0);for (int i = 1; i <= N; ++i) {char c = S[i - 1];int dx = 0, dy = 0;if (c == 'N') dx = -1;else if (c == 'S') dx = 1;else if (c == 'W') dy = -1;else if (c == 'E') dy = 1;dr[i] = dr[i - 1] + dx;dc[i] = dc[i - 1] + dy;}unordered_map<pair<int, int>, vector<int>, pair_hash> pos_map;pos_map[{0, 0}].push_back(0); // Initial smoke at time 0int current_r = 0, current_c = 0;for (int s = 1; s <= N; ++s) {char c = S[s - 1];int dx = 0, dy = 0;if (c == 'N') dx = -1;else if (c == 'S') dx = 1;else if (c == 'W') dy = -1;else if (c == 'E') dy = 1;int new_r = current_r + dx;int new_c = current_c + dy;if (new_r != 0 || new_c != 0) {// Generate new smoke at (0, 0)current_r = 0;current_c = 0;pos_map[{dr[s], dc[s]}].push_back(s);} else {current_r = new_r;current_c = new_c;}}string ans;for (int t = 1; t <= N; ++t) {int target_dr = dr[t] - R;int target_dc = dc[t] - C;auto it = pos_map.find({target_dr, target_dc});bool found = false;if (it != pos_map.end()) {const vector<int>& v = it->second;auto it2 = lower_bound(v.begin(), v.end(), t + 1);if (it2 != v.begin()) {found = true;}}ans.push_back(found ? '1' : '0');}cout << ans << endl;return 0;
}