AtCoder Beginner Contest 302
A - Attack
#include <bits/stdc++.h>
using namespace std;
#define int long long
int32_t main() {
int a , b;
cin >> a >> b;
cout << (a+b-1) / b << "\n";
return 0;
}
B - Find snuke
直接枚举八个方向,暴力判断。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int dx[] = {0, 0, 1, -1, 1, 1, -1, -1};
const int dy[] = {1, -1, 0, 0, 1, -1, 1, -1};
const string p = "snuke";
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int n, m;
cin >> n >> m;
vector<string> g(n);
for (auto &i: g) cin >> i;
for ( auto i : g )
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
for (int l = 0, f; l < 8; l++) {
if (i + dx[l] * 4 < 0 || i + dx[l] * 4 >= n || j + dy[l] * 4 < 0 || j + dy[l] * 4 >= m) continue;
f = 1;
for (int x = i, y = j, t = 0; f && t < 5; t++, x += dx[l], y += dy[l])
if (g[x][y] != p[t]) f = 0;
if (f == 0) continue;
for (int x = i, y = j, t = 0; f && t < 5; t++, x += dx[l], y += dy[l])
cout << x+1 << " " << y+1 << "\n";
return 0;
}
return 0;
}
C - Almost Equal
枚举全排列,然后暴力判断
#include <bits/stdc++.h>
using namespace std;
#define int long long
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int n, m;
cin >> n >> m;
vector<string> g(n);
for (auto &i: g) cin >> i;
sort(g.begin(), g.end());
do{
int f = 1;
for( int i = 1 , cnt ; f && i < n ; i ++ ){
cnt = 0;
for( int j = 0 ; j < m ; j ++ )
cnt += ( g[i][j] != g[i-1][j] );
if( cnt != 1 ) f = 0;
}
if( f == 0 ) continue;
cout << "Yes\n";
return 0;
}while(next_permutation(g.begin(),g.end()));
cout << "No\n";
return 0;
}
D - Impartial Gift
枚举一个,二分另一个即可。
#include <bits/stdc++.h>
using namespace std;
#define int long long
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int n, m, d;
cin >> n >> m >> d;
vector<int> a(n), b(m);
for (auto &i: a) cin >> i;
for (auto &i: b) cin >> i;
sort(a.begin(),a.end()) , sort(b.begin(),b.end());
int res = -1;
for( auto i : a ){
auto j = lower_bound(b.begin(),b.end(),i+d);
while( j != b.begin() && (j == b.end() || (*j) > i + d) ) j = prev(j);
if( abs((*j) - i ) > d ) continue;
res = max( res , (*j) + i );
}
cout << res << "\n";
return 0;
}
E - Isolation
其实直接维护一下每个点连边情况,动态的统计答案就好了。
#include <bits/stdc++.h>
using namespace std;
#define int long long
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int n, q, cnt;
cin >> n >> q, cnt = n;
vector<set<int>> e(n + 1);
for (int op, u, v; q; q--) {
cin >> op;
if (op == 1) {
cin >> u >> v;
if (e[u].empty()) cnt--;
if (e[v].empty()) cnt--;
e[u].insert(v), e[v].insert(u);
} else {
cin >> u;
for (auto v: e[u]) {
e[v].erase(u);
if (e[v].empty()) cnt++;
}
if (!e[u].empty()) e[u].clear(), cnt++;
}
cout << cnt << "\n";
}
return 0;
}
F - Merge Set
把每一个集合当作一个虚点,把集合内的元素与集合连边,集合的点权为 1,元素的点权为 0。这样从 1 开始求一遍最短路,dis[i]
就表示了把i
和 1 联通所需的最少集合数目。那么答案就是dis[m]-1
。
#include <bits/stdc++.h>
using namespace std;
#define int long long
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int n, m;
cin >> n >> m;
vector<vector<int>> e(n + m + 2);
for (int i = 1, s; i <= n; i++) {
cin >> s;
for (int y; s; s--) {
cin >> y;
e[y].push_back(m + i), e[m + i].push_back(y);
}
}
vector<int> dis(n + m + 2, INT_MAX);
vector<bool> vis(n + m + 2, 0);
dis[1] = 0;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
q.emplace(0, 1);
while (!q.empty()) {
auto [d, u] = q.top();
q.pop();
if (vis[u]) continue;
vis[u] = 1;
for (auto v: e[u]) {
if (vis[v] || dis[v] <= d + (v <= m)) continue;
dis[v] = d + (v <= m), q.emplace(dis[v], v);
}
}
if (dis[m] == INT_MAX) cout << -1;
else cout << dis[m] - 1;
return 0;
}
G - Sort from 1 to 4
置换环可以得到数组排序(可以指定排序方式)所需交换的最小次数。其的思想是:将每个节点指向其排序后应该存放的位置,最终首位相接形成一个环,那么数组排序所需的最小交换次数为数组长度-环的数量
。
因为这里数据范围只有\([1,4]\),所以置换环的大小也就是\(2,3,4\),我们可以直接暴力的枚举置换环,然后计算置换环的数量即可。
#include <bits/stdc++.h>
using namespace std;
#define int long long
int cnt[5][5];
int32_t main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int n, res = 0;
cin >> n, res = 0;
vector<int> a(n);
for (auto &i: a) cin >> i;
auto b = a;
sort(b.begin(), b.end());
for (int i = 0; i < n; i++)
if (a[i] != b[i]) cnt[a[i]][b[i]]++;
for( int i = 1 ; i <= 4 ; i ++ ){
for( int j = i + 1 , cur ; j <= 4 ; j ++ ){
cur = min( cnt[i][j] , cnt[j][i] );
res += cur , cnt[i][j] -= cur , cnt[j][i] -= cur;
}
}
for( int i = 1 ; i <= 4 ; i ++ )
for( int j = 1 ; j <= 4 ; j ++ )
for( int k = 1 , cur ; k <= 4 ; k ++ ){
if( i == j || i == k || j == k ) continue;
cur = min( {cnt[i][j] , cnt[j][k] , cnt[k][i] } );
cnt[i][j] -= cur , cnt[j][k] -= cur , cnt[k][i] -= cur;
res += cur * 2;
}
for( int i = 2 ; i <= 4 ; i ++ )
res += cnt[1][i] * 3;
cout << res << "\n";
return 0;
}