AtCoder Beginner Contest 312

1|0A - Chord


#include <bits/stdc++.h> using namespace std; int32_t main() { ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); string s; cin >> s; if( s == "ACE" ) cout << "Yes\n"; else if( s == "BDF" ) cout << "Yes\n"; else if( s == "CEG" ) cout << "Yes\n"; else if( s == "DFA" ) cout << "Yes\n"; else if( s == "EGB" ) cout << "Yes\n"; else if( s == "FAC" ) cout << "Yes\n"; else if( s == "GBD" ) cout << "Yes\n"; else cout << "No\n"; return 0; }

2|0B - TaK Code


枚举左上角

#include <bits/stdc++.h> using namespace std; 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 (int i = 0; i + 8 < n; i++) for (int j = 0; j + 8 < m; j++) { int f = 1; for (int l = i; f && l <= i + 2; l++) for (int k = j; f && k <= j + 2; k++) if (g[l][k] != '#') f = 0; for (int l = i + 6; f && l <= i + 8; l++) for (int k = j + 6; f && k <= j + 8; k++) if (g[l][k] != '#') f = 0; for (int l = i; f && l <= i + 3; l++) if (g[l][j + 3] != '.') f = 0; for (int k = j; f && k <= j + 3; k++) if (g[i + 3][k] != '.') f = 0; for (int l = i + 5; f && l <= i + 8; l++) if (g[l][j + 5] != '.') f = 0; for (int k = j + 5; f && k <= j + 8; k++) if (g[i + 5][k] != '.') f = 0; if (f == 0) continue; cout << i + 1 << " " << j + 1 << "\n"; } return 0; }

3|0C - Invisible Hand


枚举答案x,设aAi中小于等于x的数量,设bBi中大于等于x的数量,则随着x递增,a递增,b递减。所以ba递减,所以可以二分找到最小的x满足ba=0。在计算a,b的时候也可直接二分。

#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<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()); auto f = [a, b](int x) { int A = lower_bound(a.begin(), a.end(), x) - a.begin(); while (a[A] == x) A++; int B = lower_bound(b.begin(), b.end(), x) - b.begin(); B = b.size() - B; return B - A; }; int l = 0, r = 2e9, res, mid; while (l <= r) { mid = (l + r) >> 1; if (f(mid) <= 0) res = mid ,r = mid - 1; else l = mid + 1; } cout << res << "\n"; return 0; }

再来分析,可以发现答案一定是Ai,Bi+1,所以把A,B+1放到数组C中排序,当x=0ba=M,当x=C1时,ba=M1以此类推当x=CMba=0。所以第M小就是答案。

这里只求第M小,可以只用nth_element就可以O(N)求解

#include<bits/stdc++.h> using namespace std; int32_t main() { int n , m; cin >> n >> m; vector<int> a(n+m); for( int i = 0 ; i < n ; i ++ ) cin >> a[i]; for( int i = n ; i < n+m ; i ++ ) cin >> a[i] , a[i] ++; nth_element( a.begin() , a.begin() + m - 1 , a.end()); cout << a[m-1]; return 0; }

4|0D - Count Bracket Sequences


简单 dp,f[i][j]表示前i个字符,且j个左括号尚未匹配的方案数

#include <bits/stdc++.h> using namespace std; #define int long long const int N = 3005; const int mod = 998244353; int f[N][N]; int32_t main() { ios::sync_with_stdio(false), cin.tie(nullptr); string s; cin >> s; int n = s.size(); f[0][0] = 1; for( int i = 1 ; i <= n ; i ++ ){ if( s[i-1] == '(' ){ for( int j = 1 ; j <= n ; j ++ ) f[i][j] = f[i-1][j-1]; }else if( s[i-1] == ')' ){ for( int j = 0 ; j < n ; j ++ ) f[i][j] = f[i-1][j+1]; }else { for( int j = 0 ; j <= n ; j ++ ){ if( j-1 >= 0 ) f[i][j] += f[i-1][j-1]; if( j+1 <= n ) f[i][j] += f[i-1][j+1]; f[i][j] %= mod; } } } cout << f[n][0] << "\n"; return 0; }

5|0E - Tangency of Cuboids


因为长方体不会相交,所以我们暴力的标记每个立方体属于哪一个长方体,我们用每个立方体左上角的坐标表示该立方体。

如果两个长方体相邻,这会有两个相邻的立方体属于两个不同长方体。所以可以直接枚举立方体。

#include<bits/stdc++.h> using namespace std; const int N = 115; int g[N][N][N]; int32_t main() { int n; cin >> n; for (int t = 1, a, b, c, x, y, z; t <= n; t++) { cin >> a >> b >> c >> x >> y >> z; for ( int i = a ; i < x; i++) for ( int j = b ; j < y; j++) for ( int k = c ; k < z; k++) g[i][j][k] = t; } vector ans( n+1 , set<int>() ); for (int i = 0; i < 100; i++) for (int j = 0; j < 100; j++) for (int k = 0; k < 100; k++) { if (g[i][j][k] == 0) continue; if (g[i + 1][j][k] != 0 && g[i][j][k] != g[i + 1][j][k]) ans[g[i][j][k]].emplace(g[i + 1][j][k]), ans[g[i + 1][j][k]].emplace(g[i][j][k]); if (g[i][j + 1][k] != 0 && g[i][j][k] != g[i][j + 1][k]) ans[g[i][j][k]].emplace(g[i][j + 1][k]), ans[g[i][j + 1][k]].emplace(g[i][j][k]); if (g[i][j][k + 1] != 0 && g[i][j][k] != g[i][j][k + 1]) ans[g[i][j][k]].emplace(g[i][j][k + 1]), ans[g[i][j][k + 1]].emplace(g[i][j][k]); } for (int i = 1; i <= n; i++) cout << ans[i].size() << "\n"; return 0; }

6|0F - Cans and Openers


我们可以枚举选择多少个易拉罐,然后可以用二分的方式求出最多可以获得多少个普通罐。

对于易拉罐、普通罐、开罐器我们都可以贪心的选择,所以可以排序求前缀和。

#include <bits/stdc++.h> using namespace std; #define int long long const int N = 3005; const int mod = 998244353; int f[N][N]; int32_t main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n, m, res = 0; cin >> n >> m; vector<int> a, b, c; a.push_back(0), b.push_back(0), c.push_back(0); for (int i = 1, t, x; i <= n; i++) { cin >> t >> x; if (t == 0) a.push_back(x); else if (t == 1) b.push_back(x); else c.push_back(x); } int A = a.size() - 1, B = b.size() - 1, C = c.size() - 1; sort(a.begin() + 1, a.end(), greater<int>()); for (int i = 1; i <= A; i++) a[i] += a[i - 1]; sort(b.begin() + 1, b.end(), greater<int>()); for (int i = 1; i <= B; i++) b[i] += b[i - 1]; sort(c.begin() + 1, c.end(), greater<int>()); for (int i = 1; i <= C; i++) c[i] += c[i - 1]; for (int i = 0, l, r, cnt, mid; i <= min(m, A); i++) { l = 0, r = min(B, m - i), cnt = 0; while (l <= r) { mid = (l + r) >> 1; if (c[min(C, m - i - mid)] >= mid) cnt = mid, l = mid + 1; else r = mid - 1; } res = max(res, a[i] + b[cnt]); } cout << res << "\n"; return 0; }

7|0G - Avoid Straight Line


首先不管题目要求,任意选三个Cn2,然后减去三个点在一条链上的情况。

我们枚举中间点,考虑两个端点只有两种情况

  1. 一个点子树中的节点,另一个不是
  2. 两个点都是子树中的,且属于不同的子树

这样简单的分类讨论一下就可以了。

#include <bits/stdc++.h> using namespace std; #define int long long vector<vector<int>> e, g; vector<int> f; void dfs(int x) { f[x] = 1; for (auto y: e[x]) { if (f[y]) continue; g[x].push_back(y); dfs(y); f[x] += f[y]; } return; } int32_t main() { ios::sync_with_stdio(false), cin.tie(nullptr); int n; cin >> n; e.resize(n + 1), g.resize(n + 1); for (int i = 1, x, y; i < n; i++) cin >> x >> y, e[x].push_back(y), e[y].push_back(x); f.resize(n + 1); dfs(1); int res = n * (n - 1) * (n - 2) / 6; // f[i]i i的子树大小, cnt 中间包含 i的链的数量 for (int i = 1 , cnt ; i <= n; i++){ cnt = 0; for( auto j : g[i] ) // 两个点在不同的子树中 cnt += f[j] * ( f[i] - 1 - f[j] ); cnt /= 2; cnt += ( f[i] - 1 ) * ( n - f[i] ); res -= cnt; } cout << res; return 0; }

__EOF__

本文作者PHarr
本文链接https://www.cnblogs.com/PHarr/p/17594330.html
关于博主:前OIer,SMUer
版权声明CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
posted @   PHarr  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示