646 字
2 分钟
Atcoder_Beginner_Contest_463(A~D题)

题目链接:https://atcoder.jp/contests/abc463/tasks
A - 16:9
直接判断是否 即可。
#include <bits/stdc++.h>
using namespace std;using ll = long long;#define endl '\n'#define mod 998244353typedef pair<ll, ll> pll;typedef pair<int, int> pii;
void solved() { int x, y; cin >> x >> y; cout << ((9 * x == 16 * y) ? "Yes" : "No") << endl;}
int main() { ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); int _ = 1; //cin >> _; while (_--) { solved(); } return 0;}B - Train Reservation
直接遍历字符串数组判断对应的下标是否为,是就将标记为真然后输出即可。
#include <bits/stdc++.h>
using namespace std;using ll = long long;#define endl '\n'#define mod 998244353typedef pair<ll, ll> pll;typedef pair<int, int> pii;
void solved() { int N; char X; cin >> N >> X; vector<string> S(N + 1); for(int i = 1; i <= N;i++) cin >> S[i]; bool has_seat = false; for(int i = 1; i <= N;i++){ if(S[i][X - 'A'] == 'o') has_seat = true; } cout << ((has_seat) ? "Yes" : "No") << endl;}
int main() { ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); int _ = 1; //cin >> _; while (_--) { solved(); } return 0;}C - Tallest at the Moment
这题的数据大小限制我们查询时只能用一次级别的查找。同时数组根据题目条件可知保证不降序,我们可以二分找到第一个大于的下标,(为整数,所以大于等于只能是后面的下标)然后输出对应要查询的下标的答案。这个答案我们可以通过倒序遍历数组,对于每个不断更新最大值,然后存入来得到。
#include <bits/stdc++.h>
using namespace std;using ll = long long;#define endl '\n'#define mod 998244353typedef pair<ll, ll> pll;typedef pair<int, int> pii;
int H[300010];int L[300010];int suffix_max[300010];
void solved() { int N, Q; cin >> N; for (int i = 1; i <= N;i++){ cin >> H[i] >> L[i]; } suffix_max[N] = H[N]; for(int i = N - 1; i >= 1; i--){ suffix_max[i] = max(suffix_max[i + 1], H[i]); } cin >> Q; while(Q--){ int T; cin >> T; int pos = upper_bound(L + 1, L + 1 + N, T) - L; cout << suffix_max[pos] << endl; }}
int main() { ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); int _ = 1; //cin >> _; while (_--) { solved(); } return 0;}D - Maximize the Gap
这题我们先要深入理解一下题意。它要我们找互不覆盖的两块布上两个点的最小值,其实这个最小值就是在这两块布中,相对靠前的那块的右端点和相对靠后的左端点之间的距离。然后在能选出的个互不覆盖的布的前提下,找到这个距离最小能达到的最大值。所以我们根据题意,这个距离最小只会在所有满足相邻且互不覆盖的两个布之间出现。我们就在这些布里面找出最大值即可。
这题的思路依旧是二分,我们对于一个给定的距离最大值,判断它是否满足个布的距离都大于等于这个条件,满足就继续找更大的,否则就找更小的。对于这个条件的判断我们在中的用到了一种区间调度贪心的思想:
也就是选择结束时间较早(右端点较小)的区间,跳过重叠的区间,找到不重叠的区间的左端点再进行判断。这种方法可以保证避免选择到重叠的区间,同时不遗漏可能的答案,做出局部且全局最优的选择。
这里具体的实现就是按右端点从小到大排序,然后在遍历循环判断时检查后区间的左端点是否和前区间的右端点距离大于等于。满足条件才会更新和。
整体复杂度为排序加上二分内嵌遍历:,可以通过本题。
#include <bits/stdc++.h>
using namespace std;using ll = long long;#define endl '\n'#define mod 998244353typedef pair<ll, ll> pll;typedef pair<int, int> pii;
void solved() { int n, k; cin >> n >> k; vector<pii> cloth(n); for(int i = 0; i < n;i++){ int L, R; cin >> L >> R; cloth[i] = {R, L}; } //按右端点从小到大排序 sort(cloth.begin(), cloth.end()); //判断对于一个给定的距离,是否存在k个布能满足。 auto check = [&](int distance) -> bool { int cnt = 0; ll last_right = -(1LL << 60);//让第一个右端点一定能初始化 for(auto [R, L] : cloth){ if(L >= last_right + distance){ cnt++; last_right = R; if(cnt >= k) return true; } } return false; }; //查找可能满足的最小得分的最大值,尽可能向右(大)搜 int left = 1, right = 1e9, ans = -1; while(left <= right){ int mid = left + (right - left) / 2; if(check(mid)){ ans = mid; left = mid + 1; } else{ right = mid - 1; } } cout << ans << endl;}
int main() { ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); int _ = 1; //cin >> _; while (_--) { solved(); } return 0;}Atcoder_Beginner_Contest_463(A~D题)
https://mkrari.cn/posts/abc_463/