AtCoder Beginner Contest 322
A - First ABC 2 (abc322 A)
题目大意
给定一个字符串,找到最先出现ABC
的位置。
解题思路
直接查找判断即可。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n; string s; cin >> n >> s; int pos = s.find("ABC"); if (pos == string::npos) pos = -2; cout << pos + 1 << '\n'; return 0; }
B - Prefix and Suffix (abc322 B)
题目大意
给定字符串 s
和t
,问s
是不是t
的前缀和后缀。
解题思路
根据前后缀定义判断即可。这里试了下python
神奇的代码
n, m = map(int, input().split(' ')) s = input() t = input() prefix = t.startswith(s) suffix = t.endswith(s) if prefix and suffix: print(0) elif prefix and not suffix: print(1) elif not prefix and suffix: print(2) else: print(3)
C - Festival (abc322 C)
题目大意
天,有天会放烟花。
问每一天,距离未来最近的放烟花的天数。
解题思路
两个双指针一样,一个指针指向当前天数,一个指针指向未来最近的放烟花的天数,两者差就是答案。然后两个指针不断往未来移动。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, m; cin >> n >> m; vector<int> day(m); for (auto& i : day) cin >> i; int cur = 0; for (int i = 1; i <= n; ++i) { if (i > day[cur]) ++cur; cout << day[cur] - i << '\n'; } return 0; }
D - Polyomino (abc322 D)
题目大意
给定三个多米诺骨牌,问能否不重叠地摆成的方格。
解题思路
数不大,直接暴力搜索。
考虑搜索方式,虽然给了个的多米诺骨牌的表示形式,但我们就枚举这个 的方格的位置。
设想我们的画布就是一个的方格,然后枚举一个多米诺骨牌盖章左上角的位置(可以在这个画布之外),以及旋转的角度,然后一盖,在该区域的多米诺骨就被保留下来。最后我们就看该区域是否填满了,且没重叠,且无多米诺骨牌在外面。
代码实现里没有真正的盖,只取了盖在画布上的格子,方法类似于
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); array<array<string, 4>, 3> tu; int cnt = 0; for (auto& i : tu) for (auto& j : i) { cin >> j; cnt += count(j.begin(), j.end(), '#'); } array<array<char, 4>, 4> page{}; int dx1[2] = {1, -1}; int dy1[2] = {1, -1}; int dx2[2] = {1, -1}; int dy2[2] = {-1, 1}; auto fit1 = [&](int k, int x, int y, int d) { for (int i = 0; i < 4; ++i) for (int j = 0; j < 4; ++j) { int nx = x + dx1[d] * i, ny = y + dy1[d] * j; if (tu[k][i][j] == '#') { if (nx >= 0 && nx < 4 && ny >= 0 && ny < 4) { if (page[nx][ny] == '#') { return false; } page[nx][ny] = '#'; } else { return false; } } } return true; }; auto fit2 = [&](int k, int x, int y, int d) { for (int i = 0; i < 4; ++i) for (int j = 0; j < 4; ++j) { int nx = x + dx2[d] * j, ny = y + dy2[d] * i; if (tu[k][i][j] == '#') { if (nx >= 0 && nx < 4 && ny >= 0 && ny < 4) { if (page[nx][ny] == '#') { return false; } page[nx][ny] = '#'; } else { return false; } } } return true; }; function<bool(int)> ok = [&](int k) { if (k == 3) { return true; } auto bak = page; for (int x = -3; x <= 7; ++x) for (int y = -3; y <= 7; ++y) { for (int d = 0; d < 2; ++d) { if (fit1(k, x, y, d)) { if (ok(k + 1)) return true; } page = bak; if (fit2(k, x, y, d)) { if (ok(k + 1)) return true; } page = bak; } } return false; }; if (cnt == 16 && ok(0)) cout << "Yes" << '\n'; else cout << "No" << '\n'; return 0; }
上述代码实际上没有真正旋转,在盖章的时候考虑了角度,而旋转跟的考虑逻辑不一样,因此代码会比较长,下述代码则真正旋转了矩阵,代码简洁点,不过运行时间会长一点点(指长了)
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); array<array<string, 4>, 3> tu; int cnt = 0; for (auto& i : tu) for (auto& j : i) { cin >> j; cnt += count(j.begin(), j.end(), '#'); } array<array<char, 4>, 4> page{}; auto fit = [&](int k, int x, int y) { for (int i = 0; i < 4; ++i) for (int j = 0; j < 4; ++j) { int nx = x + i, ny = y + j; if (tu[k][i][j] == '#') { if (nx >= 0 && nx < 4 && ny >= 0 && ny < 4) { if (page[nx][ny] == '#') { return false; } page[nx][ny] = '#'; } else { return false; } } } return true; }; auto rotate = [&](const array<string, 4>& a) { auto ret = a; for (int i = 0; i < a.size(); ++i) { for (int j = 0; j < a.front().size(); ++j) ret[j][a.size() - i - 1] = a[i][j]; } return ret; }; function<bool(int)> ok = [&](int k) { if (k == 3) { return true; } auto bak = page; for (int x = -3; x <= 7; ++x) for (int y = -3; y <= 7; ++y) { for (int r = 0; r < 4; ++r) { if (fit(k, x, y)) { if (ok(k + 1)) return true; } tu[k] = rotate(tu[k]); page = bak; } } return false; }; if (cnt == 16 && ok(0)) cout << "Yes" << '\n'; else cout << "No" << '\n'; return 0; }
E - Product Development (abc322 E)
题目大意
一个产品,有个性能参数,初始为,要求进行一些提升计划,使得每个性能参数不小于 ,且代价最小。
每个提升计划包含一个代价,以及对这个性能参数提升的数值。
解题思路
注意到最大都只有 。考虑搜索状态,我们可以设 表示前 个提升计划,使得最终性能参数分别为 的最小代价。转移就考虑当前提升计划选或不选即可。
但这里的 不一定是 ,也就是说这个 的维度不是固定的,但由于每一维度的取值只有 共 种情况,最多 维,因此我们可以把这最后的 维压缩成一维的 进制数表示。
由于 只依赖于 ,因此第一维可以滚动数组优化掉。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; const LL inf = 1e18; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, k, p; cin >> n >> k >> p; int base = p + 1; const int sz = int(pow(base, k)); vector<LL> dp(sz, inf); dp[0] = 0; auto dtr = [&](int x) { vector<int> ret(k); for (int i = k - 1; i >= 0; --i) { ret[i] = x % base; x /= base; } return ret; }; auto tr = [&](const vector<int>& x) { int ret = 0; for (int i = 0; i < k; ++i) { ret = ret * base + x[i]; } return ret; }; for (int i = 0; i < n; ++i) { int c; cin >> c; vector<int> x(k); vector<LL> dp2 = dp; for (auto& i : x) cin >> i; for (int j = 0; j < sz; ++j) { auto now = dtr(j); for (int i = 0; i < k; ++i) now[i] = min(p, now[i] + x[i]); auto nxt = tr(now); dp2[nxt] = min(dp2[nxt], dp[j] + c); } dp.swap(dp2); } LL ans = dp.back(); if (ans == inf) ans = -1; cout << ans << '\n'; return 0; }
F - Vacation Query (abc322 F)
题目大意
给定一个串。维护两种操作。
- ,将的数字翻转。
- ,问中最长的连续的的长度。
解题思路
不考虑修改,仅考虑查询。
考虑如何求解,对于每个,我们要找最小的 满足 ,其中 表示 中 的个数。
但这涉及到特定区间的信息,感觉难以维护。
注意到问的是连续的,还有一种思路是考虑区间信息的合并,即一个区间的最长连续段,要么在左区间,要么在右区间,要么是左区间的后缀和右区间的前缀合并起来。与此相关的其他信息(区间最长连续 的前缀 、后缀长度、是否全是,这些信息都可以合并),因此可以用线段树维护区间的上述信息,对于每个区间答案,合并次区间信息即可得到 。
考虑修改,事实上就是把看成 , 看成 。因此我们分别对 这两个数维护上述信息,修改时交换一下这两个信息即可。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; const int N = 5e5 + 8; class segment { #define lson root << 1 #define rson root << 1 | 1 struct node { struct info { int ans, l, r; bool all; } _info[2]; bool flip; node operator+(const node& o) { node ret; ret.flip = 0; for (int i = 0; i < 2; ++i) { const auto &L = _info[i], R = o._info[i]; ret._info[i].ans = max({L.ans, R.ans, L.r + R.l}); ret._info[i].l = L.l; ret._info[i].r = R.r; if (L.all) ret._info[i].l = L.l + R.l; if (R.all) ret._info[i].r = L.r + R.r; ret._info[i].all = (L.all && R.all); } return ret; } void swap_info() { swap(_info[0], _info[1]); } int ans() { return _info[1].ans; } } a[N << 2]; public: void build(int root, int l, int r, const string& s) { if (l == r) { a[root].flip = 0; for (int i = 0; i < 2; ++i) { auto& info = a[root]._info[i]; info.l = info.r = info.all = info.ans = (s[l - 1] == '0' + i); } return; } int mid = (l + r) >> 1; build(lson, l, mid, s); build(rson, mid + 1, r, s); a[root] = a[lson] + a[rson]; } void pushdown(int root) { if (a[root].flip) { a[lson].flip ^= 1; a[lson].swap_info(); a[rson].flip ^= 1; a[rson].swap_info(); a[root].flip = 0; } } void update(int root, int l, int r, int ll, int rr) { if (ll <= l && r <= rr) { a[root].flip ^= 1; a[root].swap_info(); return; } pushdown(root); int mid = (l + r) >> 1; if (ll <= mid) update(lson, l, mid, ll, rr); if (rr > mid) update(rson, mid + 1, r, ll, rr); a[root] = a[lson] + a[rson]; } node query(int root, int l, int r, int ll, int rr) { if (ll <= l && r <= rr) { return a[root]; } pushdown(root); int mid = (l + r) >> 1; node L, R; if (ll <= mid) L = query(lson, l, mid, ll, rr); if (rr > mid) R = query(rson, mid + 1, r, ll, rr); if (ll > mid) return R; else if (rr <= mid) return L; else return L + R; } } seg; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, q; cin >> n >> q; string s; cin >> s; seg.build(1, 1, n, s); while (q--) { int c, l, r; cin >> c >> l >> r; if (c == 1) { seg.update(1, 1, n, l, r); } else { auto ans = seg.query(1, 1, n, l, r); cout << ans.ans() << '\n'; } } return 0; }
G - Two Kinds of Base (abc322 G)
题目大意
给定,问有多少组 ,满足下述条件:
- 是一个序列,长度随意,
- 设是进制的表示形式时,其值为, 进制的表示形式时,其值为 ,要求
解题思路
<++>
神奇的代码
本文作者:~Lanly~
本文链接:https://www.cnblogs.com/Lanly/p/17738474.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步