295? 上周ECF玩去了,咕咕咕
A - Alternately (abc296 a)
题目大意
给定一个包含\(MF\)的字符串,问是否是 \(M,F\)交替出现的。
解题思路
判断相邻字母是否相等即可。
神奇的代码
#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)
题目大意
给定一个仅包含一个*
,其余都是.
的二维\(8 \times 8\)的矩阵,要求输出该*
的位置。从左到右依次编号 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)
题目大意
给定一个数组\(A\),问是否存在两个数,其差为 \(x\)。这两个数可以相等。
解题思路
特判\(x=0\)的情况,剩下的把所有数存到 \(set\)里,对于当前一个数 \(a\),看看是否存在 \(a+x\)或 \(a-x\)即可。
实现是反过来的。
神奇的代码
#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)
题目大意
给定\(n,m\),问是否存在\(a,b \leq n\),且 \(a \times b \geq m\),输出最小的 \(a \times b\)
解题思路
从小到大\(a\),则满足题意的最小的 \(b= \lceil \frac{m}{a} \rceil\),容易发现会有多个\(a\),其 \(b= \lceil \frac{m}{a} \rceil\)是相同的,而显然我们只考虑这一块中最小的\(a\)即可,然后再考虑下一块\(a\),这一块的\(a\)会使得 \(B = b + 1\),同样取最小的 \(a\),依次考虑。
实际上就是对\(\lceil \frac{m}{a} \rceil\)进行数论分块,时间复杂度是\(O(\sqrt{m})\)
神奇的代码
#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)
题目大意
给定一个长度为\(n\)的数组 \(A\),值域 \(1 \sim n\)。
对于 \(i = 1,2,\cdots, n\),高桥和青木依次玩一个游戏:
- 青木先写一个数 \(k \in [1, n]\)。
- 高桥根据这个 \(k\),再写一个数 \(x \in [1,n]\)。
- 令 \(x = A_x\),执行\(k\)遍后,如果变成 \(i\),则高桥获胜,否则青木获胜。
问高桥获胜的游戏数。
解题思路
首先建个图,有向边\(x \to A_x\)。变换操作就是在这样图上游走 \(k\)次,最后停在\(i\)号点就算胜利。
根据定义这是一个基环内向森林,即从任意点出发最后一定会走到一个环里。
容易发现如果\(i\)在一个环里的话是必赢的,高桥肯定可以选择环上的一个点走 \(k\)次到达 \(i\)。
而如果不在环上,则必寄了,因为青木只要写个 \(n\),最后一定会走到环上的。事实上只要 \(k\)大过 \(i\)号点之前的点(反向图中可到达的点)的数量就寄了。
因此答案就是在环上的点的数量。
对该图跑一遍拓扑排序即可得到答案。
神奇的代码
#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)
题目大意
给定两个数组\(A,B\),每次交换选择 \(i,j,k\),交换 \(A_i,A_j\), \(B_i,B_k\)。
问最后两个数组能否相等。
解题思路
首先两个数组的各个数字的数量一定要相等。
然后假设可以交换到相等,然后我们令\(j=k\),这样就可以将两者交换成递增的顺序,方便之后考虑。(就是说可以先对数组 \(A\)排个序,数组\(B\)跟随变动,不会影响到可不可行)
此时考虑数组\(A\)递增的情况下怎么操作,将数组\(B\)也变得递增,且数组 \(A\)不动。
一个朴素的思想就是能否找到一个元操作,即经过这个操作, 数组\(A\)不变,且数组\(B\)跟像数组 \(A\)了。
考虑从左到右第一个 \(A_{i_1} \neq B_{i_1}\)的位置 ,考虑\(j_1,k_1\)取什么值。很显然\(k_1\)要满足\(B_{k_1} = A_{i_1}\),这样经过这次交换,数组 \(B\)就能更像数组 \(A\)了。但由于\(A_{i_1}\)和 \(A_{j_1}\)交换了,下一个操作我们得换回来,但不该过多影响到\(B\)。
下一个操作,我们令\(i_2 = j_1\),即上一个操作中的 \(j_1\),而 \(j_2 = i_1\),此时会交换 \(A_{j_1}\)和 \(A_{i_1}\) ,即又交换回来了。而这个操作我们会交换\(B_{i_2}\)和 \(B_{k_2}\),即\(B_{j_1}\)和 \(B_{k_2}\),如果说 \(B_{j_1} = B_{k_2}\),那么经过这次操作不会影响到数组\(B\),此时 \(j_1\)和 \(k_2\)的值也确定了。
我们就找到了一个元操作,经过这个操作, 数组\(A\)不变,且数组\(B\)多了一个位置和数组 \(A\)相同,然后我们依次进行元操作,就能变成一样了。前提是存在两个相等的数。
即如果有出现了两次及以上的数,则必可以。
那就剩下各个数都仅出现一次的情况,我们找不到满足 \(B_{j_1}=B_{k_2}\)的情况,那就只能经过这次操作,使得数组\(B\)进一步更像数组\(A\),即选择 \(j_1 = x\), \(B_{k_2} = A_{j_1}\),其中\(x\)是下一个 \(A_x \neq B_x\)的位置。即经过这次操作,还原了数组 \(A\)的影响,且数组 \(B\)又有一位和数组 \(A\)相同了。
即另一个元操作,数组 \(A\)不变,数组 \(B\)多了两个位置和数组\(A\)相同。但由于交换了两次,数组\(B\)的逆序数的奇偶性是不改变的,由于数组\(A\)是递增的,其逆序数为\(0\)。因此只有数组 \(B\) 的逆序数也为偶数时,才可以交换到和数组\(A\)一样的,否则不可以。
综上,
- 两个数组各个数字的数量不同,则
No
- 存在一个数字出现大于\(1\)次,则
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)
题目大意
<++>
解题思路
<++>
神奇的代码
- Beginner AtCoder Contest 296beginner atcoder contest 296 contest programming beginner atcoder beginner atcoder contest 295 beginner atcoder contest abcde beginner atcoder contest 335 beginner atcoder contest 332 beginner atcoder contest 328 beginner atcoder contest 334 beginner atcoder contest 310 beginner atcoder contest 315