AtCoder Beginner Contest 296
295? 上周ECF玩去了,咕咕咕
A - Alternately (abc296 a)
题目大意
给定一个包含的字符串,问是否是 交替出现的。
解题思路
判断相邻字母是否相等即可。
神奇的代码
#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; auto check = [&](){ for(int i = 0; i < n - 1; ++ i) if (s[i] == s[i + 1]) return false; return true; }; if (check()) cout << "Yes" << '\n'; else cout << "No" << '\n'; return 0; }
B - Chessboard (abc296 b)
题目大意
给定一个仅包含一个*
,其余都是.
的二维的矩阵,要求输出该*
的位置。从左到右依次编号 a,b,c,d,e,f,g,h
,从下到上依次编号1,2,3,4,5,6,7,8
解题思路
按题意模拟即可。
神奇的代码
#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 x, y; for(int i = 0; i < 8; ++ i){ string s; cin >> s; int pos = s.find('*'); if (pos != string::npos){ x = 8 - i; y = 'a' + pos; } } cout << char(y) << x << '\n'; return 0; }
C - Gap Existence (abc296 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, x; cin >> n >> x; auto check = [&](){ set<int> qwq; for(int i = 0; i < n; ++ i){ int a; cin >> a; if (qwq.find(a) != qwq.end() || qwq.find(a) != qwq.end()) return true; qwq.insert(a - x); qwq.insert(a + x); } return x == 0; }; if (check()) cout << "Yes" << '\n'; else cout << "No" << '\n'; return 0; }
D - M<=ab (abc296 d)
题目大意
给定,问是否存在,且 ,输出最小的
解题思路
从小到大,则满足题意的最小的 ,容易发现会有多个,其 是相同的,而显然我们只考虑这一块中最小的即可,然后再考虑下一块,这一块的会使得 ,同样取最小的 ,依次考虑。
实际上就是对进行数论分块,时间复杂度是
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; const LL maxx = 1e18; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); LL n, m; cin >> n >> m; LL ans = maxx; LL l = 1, r; while (l <= m) { r = m / (m / l); LL ano = (m + l - 1) / l; if (l <= n && ano <= n) ans = min(ans, l * ano); l = r + 1; } if (ans == maxx) ans = -1; cout << ans << '\n'; return 0; }
E - Transition Game (abc296 e)
题目大意
给定一个长度为的数组 ,值域 。
对于 ,高桥和青木依次玩一个游戏:
- 青木先写一个数 。
- 高桥根据这个 ,再写一个数 。
- 令 ,执行遍后,如果变成 ,则高桥获胜,否则青木获胜。
问高桥获胜的游戏数。
解题思路
首先建个图,有向边。变换操作就是在这样图上游走 次,最后停在号点就算胜利。
根据定义这是一个基环内向森林,即从任意点出发最后一定会走到一个环里。
容易发现如果在一个环里的话是必赢的,高桥肯定可以选择环上的一个点走 次到达 。
而如果不在环上,则必寄了,因为青木只要写个 ,最后一定会走到环上的。事实上只要 大过 号点之前的点(反向图中可到达的点)的数量就寄了。
因此答案就是在环上的点的数量。
对该图跑一遍拓扑排序即可得到答案。
神奇的代码
#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; cin >> n; vector<vector<int>> edge(n); vector<int> du(n, 0); for(int i = 0; i < n; ++ i){ int a; cin >> a; -- a; edge[i].push_back(a); du[a] ++; } queue<int> team; for(int i = 0; i < n; ++ i){ if (du[i] == 0) team.push(i); } int ans = n; while(!team.empty()){ int u = team.front(); team.pop(); -- ans; for(auto v : edge[u]){ du[v] --; if (du[v] == 0) team.push(v); } } cout << ans << '\n'; return 0; }
F - Simultaneous Swap (abc296 f)
题目大意
给定两个数组,每次交换选择 ,交换 , 。
问最后两个数组能否相等。
解题思路
首先两个数组的各个数字的数量一定要相等。
然后假设可以交换到相等,然后我们令,这样就可以将两者交换成递增的顺序,方便之后考虑。(就是说可以先对数组 排个序,数组跟随变动,不会影响到可不可行)
此时考虑数组递增的情况下怎么操作,将数组也变得递增,且数组 不动。
一个朴素的思想就是能否找到一个元操作,即经过这个操作, 数组不变,且数组跟像数组 了。
考虑从左到右第一个 的位置 ,考虑取什么值。很显然要满足,这样经过这次交换,数组 就能更像数组 了。但由于和 交换了,下一个操作我们得换回来,但不该过多影响到。
下一个操作,我们令,即上一个操作中的 ,而 ,此时会交换 和 ,即又交换回来了。而这个操作我们会交换和 ,即和 ,如果说 ,那么经过这次操作不会影响到数组,此时 和 的值也确定了。
我们就找到了一个元操作,经过这个操作, 数组不变,且数组多了一个位置和数组 相同,然后我们依次进行元操作,就能变成一样了。前提是存在两个相等的数。
即如果有出现了两次及以上的数,则必可以。
那就剩下各个数都仅出现一次的情况,我们找不到满足 的情况,那就只能经过这次操作,使得数组进一步更像数组,即选择 , ,其中是下一个 的位置。即经过这次操作,还原了数组 的影响,且数组 又有一位和数组 相同了。
即另一个元操作,数组 不变,数组 多了两个位置和数组相同。但由于交换了两次,数组的逆序数的奇偶性是不改变的,由于数组是递增的,其逆序数为。因此只有数组 的逆序数也为偶数时,才可以交换到和数组一样的,否则不可以。
综上,
- 两个数组各个数字的数量不同,则
No
- 存在一个数字出现大于次,则
Yes
- 两个数组的逆序数奇偶性相同,则
Yes
,不同则No
统计逆序数就用归并或者树状数组就可以了。
最后一个情况是手玩以下例子发现的
1 2 3 4 4 3 2 1 1 2 3 4 4 2 3 1
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; template <typename T> class fenwick { public: vector<T> fenw; int n; LL tot; fenwick(int _n) : n(_n) { fenw.resize(n); tot = 0; } void modify(int x, T v) { while (x < n) { fenw[x] += v; x |= (x + 1); } tot += v; } T get(int x) { T v{}; while (x >= 0) { v += fenw[x]; x = (x & (x + 1)) - 1; } return v; } }; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n; cin >> n; map<int, int> cnt; map<int, int> acnt; vector<int> A(n), B(n); for(int i = 0; i < n; ++ i){ int a; cin >> a; cnt[a] ++; acnt[a] ++; A[i] = a; } for(int i = 0; i < n; ++ i){ int b; cin >> b; cnt[b] --; B[i] = b; } auto nixu = [&](){ vector<int> id(n); iota(id.begin(), id.end(), 0); sort(id.begin(), id.end(), [&](int a, int b){ return A[a] < A[b]; }); fenwick<LL> cc(n + 1); LL ans = 0; for(auto &i : id){ ans += cc.tot - cc.get(B[i]); cc.modify(B[i], 1); } return ans; }; auto check = [&](){ for(auto &i : cnt) if (i.second != 0) return false; for(auto &i : acnt) if (i.second > 1) return true; return nixu() % 2 == 0; }; if (check()) cout << "Yes" << '\n'; else cout << "No" << '\n'; return 0; }
G - Polygon and Points (abc296 g)
题目大意
给定一个凸多边形和若干个点,依次回答每个点在凸多边形里面还是边上还是外面。
解题思路
<++>
神奇的代码
Ex - Unite (abc296 h)
题目大意
<++>
解题思路
<++>
神奇的代码
本文作者:~Lanly~
本文链接:https://www.cnblogs.com/Lanly/p/17279536.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2020-04-01 Codeforces Round #630 (Div. 2)