Codeforces Round 935 (Div. 3)

1|0A. Setting up Camp


#include <bits/stdc++.h> using namespace std; using i32 = int32_t; void solve() { int a, b, c; cin >> a >> b >> c; int res = a + b / 3; b %= 3; if (b != 0) { if (c < 3 - b) { cout << "-1\n"; return; } c -= 3 - b, res++; } res += ( c + 2 ) / 3 ; cout << res << "\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int TC; for (cin >> TC; TC; TC--) solve(); return 0; }

2|0B. Fireworks


计算出每种烟花同时最多看多少个,然后相加即可。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = int64_t; void solve() { i64 a, b, c; cin >> a >> b >> c , c ++; a = ( c + a - 1 ) / a; b = ( c + b - 1 ) / b; cout << a + b << "\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int TC; for (cin >> TC; TC; TC--) solve(); return 0; }

3|0C. Left and Right Houses


可以直接枚举一下路的位置,然后后缀和处理一下。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = int64_t; void solve() { int n; string s; cin >> n >> s; int l = 0, r = 0, ans; double p = 1e9; for (auto i: s) r += i == '1'; for (int i = 0; i <= n; i++) { if (l >= (i + 1) / 2 and r >= (n - i + 1) / 2) { double t = abs(0.5 * n - i); if (p > t) p = t, ans = i; } if( i < n ) l += s[i] == '0' , r-= s[i] == '1'; } cout << ans << "\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int TC; for (cin >> TC; TC; TC--) solve(); return 0; }

4|0D. Seraphim the Owl


首先我们要从前m个位置选择一个点作为终点,然后从起点到终点的过程中每个点可以任意选a,b但是终点只能是a

为什么过程中可以任意选a,b,对于每个点,如果你直接走过去就是b,如果停留一下就是a

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = int64_t; using vi = vector<i64>; const i64 inf = 1e18; void solve() { int n, m; cin >> n >> m; vi a(n + 1), b(n + 2); for (int i = 1; i <= n; i++) cin >> a[i]; for (int i = 1; i <= n; i++) cin >> b[i], b[i] = min(b[i], a[i]); for (int i = n - 1; i >= 1; i--) b[i] += b[i + 1]; i64 res = inf; for (int i = 1; i <= m; i++) res = min(res, a[i] + b[i + 1]); cout << res << "\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int TC; for (cin >> TC; TC; TC--) solve(); return 0; }

5|0E. Binary Search


我感觉是可以只通过一次操作就一定可以实现要求。

根据这个猜想,交换的一个点应该是目标数字,所以我枚举另一个点,然后进行交换,最后再模仿题目的二分进行一次 check

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using ui64 = uint64_t; #define int long long using vi = vector<int>; using pii = pair<int, int>; const int mod = 998244353; const int inf = 1e18; const vi dx = {0, 0, 1, -1, 1, 1, -1, -1}, dy = {1, -1, 0, 0, 1, -1, 1, -1}; void solve() { int n, x; cin >> n >> x; vi p(n + 1); int y; for (int i = 1; i <= n; i++) { cin >> p[i]; if (p[i] == x) y = i; } for (int i = 1, l, r; i <= n; i++) { swap(p[i], p[y]); l = 1, r = n + 1; for (int m; r - l != 1;) { m = (l + r) / 2; if (p[m] <= x) l = m; else r = m; } if (p[l] == x) { cout << "1\n" << y << " " << i << "\n"; return; } swap(p[i], p[y]); } return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int t; cin >> t; while (t--) solve(); return 0; }

6|0F. Kirill and Mushrooms


强度等于k×val,其中k是我选择的个数,val是选择的最小值。

如果我枚举出k就可以确定那些蘑菇的值为 0,然后在剩下的蘑菇中贪心的选择最大的k个,这样就可以知道val

我用multiset<int>维护两个集合,一个是cnt表示当前不为0 且没有被选到的蘑菇,q是当前被选到的最大的k个蘑菇。

然后从小到大枚举k,每次都从cnt中取最大值填入到q中,直到q.size() == k。然后随着选择数量增大,就要是的一些蘑菇变为0,也就说要从两个集合中删掉一些蘑菇,每次删除时优先从cnt中删除即可。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using ui64 = uint64_t; #define int long long using vi = vector<int>; using pii = pair<int, int>; const int mod = 998244353; const int inf = 1e18; void solve() { int n; cin >> n; multiset<int> cnt, q; vi a(n + 1); vi p(n + 1); for (int i = 1; i <= n; i++) cin >> a[i], q.insert(a[i]); for (int i = 1; i <= n; i++) cin >> p[i]; int res = -inf, val = -inf; for (int i = 1, v, x; i <= n; i++) { while (not q.empty() and cnt.size() < i) { x = *q.rbegin(); cnt.insert(x), q.erase(q.find(x)); } if (cnt.size() < i) break; v = *cnt.begin() * i; if (v > res) res = v, val = i; if (q.count(a[p[i]])) q.erase(q.find(a[p[i]])); else cnt.erase(cnt.find(a[p[i]])); } cout << res << " " << val << "\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int t; cin >> t; while (t--) solve(); return 0; }

7|0G. Cook and Porridge


这个题目实际上要求维护一个序列,但是这个序列要实现一个插队的功能。

如果把重新入队的人单独放在一个优先队列内。然后提前维护一个ki的后缀最大值sufi

如果没时刻我取出队列的第一个和优先队列中的第一个。然后比较一下后缀最值和优先队列队首权值的大小,如果后缀最值更大说明不会插队到当前的人前面,则队首出队,否则优先队列出队。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = int64_t; using vi = vector<i64>; using pii = pair<i64, i64>; const i64 inf = 1e18; #define int i64 void solve() { int n, d; cin >> n >> d; vector<pii> a(n); for (auto &[k, s]: a) cin >> k >> s; vi suf(n + 1); for (int i = n - 1; i >= 0; i--) suf[i] = max(a[i].first, suf[i + 1]); vector<vi> que(d + 1); int t = 0; set<array<int, 4>> st; for (int time = 1; time <= d; time++) { if (not st.empty() and prev(st.end())->at(0) > suf[t]) { auto [k, tim, s, id] = *prev(st.end()); s = -s; st.erase(prev(st.end())); if (time + s <= d) que[time + s].push_back(id); } else { auto [kt, st] = a[t]; if (time + st <= d) que[time + st].push_back(t); t++; } if (t == n) { cout << time << "\n"; return; } for (auto id: que[time]) { auto [ki, si] = a[id]; st.insert({ki, -time, -si, id}); } } cout << "-1\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int TC; for (cin >> TC; TC; TC--) solve(); return 0; }

__EOF__

本文作者PHarr
本文链接https://www.cnblogs.com/PHarr/p/18088311.html
关于博主:前OIer,SMUer
版权声明CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
posted @   PHarr  阅读(57)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
历史上的今天:
2023-03-21 SMU Spring 2023 Trial Contest Round 1
点击右上角即可分享
微信分享提示