Codeforces Round 923 (Div. 3)

1|0A. Make it White


#include<bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using i128 = __int128; using ldb = long double; #define int i64 using vi = vector<int>; using pii = pair<int, int>; using vii = vector<pii>; const int inf = INT_MAX, INF = 1e18; const int mod = 998244353; const vi dx = {0, 0, 1, -1}, dy = {1, -1, 0, 0}; using edge = array<int, 3>; int power(int x, int y) { int ans = 1; while (y) { if (y & 1) ans = ans * x % mod; x = x * x % mod, y /= 2; } return ans; } int inv(int x) { return power(x, mod - 2); } void solve() { int n; string s; cin >> n >> s; int l = 0 , r = n - 1; while( l < n and s[l] == 'W') l ++; while( r >= 0 and s[r] == 'W' ) r --; cout << max( 0ll , r - l + 1 ) << "\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int TC; for( cin >> TC ; TC ; TC -- ) solve(); return 0; }

2|0B. Following the String


#include<bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using i128 = __int128; using ldb = long double; #define int i64 using vi = vector<int>; using pii = pair<int, int>; using vii = vector<pii>; const int inf = INT_MAX, INF = 1e18; const int mod = 998244353; const vi dx = {0, 0, 1, -1}, dy = {1, -1, 0, 0}; using edge = array<int, 3>; int power(int x, int y) { int ans = 1; while (y) { if (y & 1) ans = ans * x % mod; x = x * x % mod, y /= 2; } return ans; } int inv(int x) { return power(x, mod - 2); } void solve() { int n; cin >> n; vi cnt(26); for (int i = 0, x; i < n; i++) { cin >> x; for (int j = 0; j < 26; j++) { if (cnt[j] != x) continue; cout << char(j + 'a'); cnt[j]++; break; } } cout << "\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int TC; for (cin >> TC; TC; TC--) solve(); return 0; }

3|0C. Choose the Different Ones!


#include<bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using i128 = __int128; using ldb = long double; #define int i64 using vi = vector<int>; using pii = pair<int, int>; using vii = vector<pii>; const int inf = INT_MAX, INF = 1e18; const int mod = 998244353; const vi dx = {0, 0, 1, -1}, dy = {1, -1, 0, 0}; using edge = array<int, 3>; int power(int x, int y) { int ans = 1; while (y) { if (y & 1) ans = ans * x % mod; x = x * x % mod, y /= 2; } return ans; } int inv(int x) { return power(x, mod - 2); } void solve() { int n, m, k; cin >> n >> m >> k; vector<bool> a(k), b(k), c(k); for (int i = 1, x; i <= n; i++) { cin >> x, x--; if (x < k) a[x] = 1, c[x] = 1; } for (int i = 1, x; i <= m; i++) { cin >> x, x--; if (x < k) b[x] = 1, c[x] = 1; } if (accumulate(a.begin(), a.end(), 0) < k / 2) { cout << "NO\n"; return; } if (accumulate(b.begin(), b.end(), 0) < k / 2) { cout << "NO\n"; return; } if (accumulate(c.begin(), c.end(), 0) < k) { cout << "NO\n"; return; } cout << "YES\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int TC; for (cin >> TC; TC; TC--) solve(); return 0; }

4|0D. Find the Different Ones!


这题我用了区间最值查询来实现

#include<bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using i128 = __int128; using ldb = long double; #define int i64 using vi = vector<int>; using pii = pair<int, int>; using vii = vector<pii>; const int inf = INT_MAX, INF = 1e18; const int mod = 998244353; const vi dx = {0, 0, 1, -1}, dy = {1, -1, 0, 0}; using edge = array<int, 3>; int power(int x, int y) { int ans = 1; while (y) { if (y & 1) ans = ans * x % mod; x = x * x % mod, y /= 2; } return ans; } int inv(int x) { return power(x, mod - 2); } int lgN; vi lg2(2e5 + 1); void solve() { int n; cin >> n; vi a(n + 1); for (int i = 1; i <= n; i++) cin >> a[i]; auto exMax = [&a](int i, int j) { if (a[i] > a[j]) return i; else return j; }; auto exMin = [&a](int i, int j) { if (a[i] < a[j]) return i; return j; }; vector f(n + 1, vi(lgN + 1)), g(n + 1, vi(lgN + 1)); for (int i = 1; i <= n; i++) f[i][0] = g[i][0] = i; for (int j = 1; j <= lgN; j++) for (int i = 1; i + (1 << j) - 1 <= n; i++) { f[i][j] = exMax(f[i][j - 1], f[i + (1 << j - 1)][j - 1]); g[i][j] = exMin(g[i][j - 1], g[i + (1 << j - 1)][j - 1]); } auto calcMax = [&exMax, &f](int l, int r) { int s = lg2[r - l + 1]; return exMax(f[l][s], f[r - (1 << s) + 1][s]); }; auto calcMin = [&exMin, &g](int l, int r) { int s = lg2[r - l + 1]; return exMin(g[l][s], g[r - (1 << s) + 1][s]); }; int q; cin >> q; for (int l, r, i, j; q; q--) { cin >> l >> r; i = calcMax(l, r), j = calcMin(l, r); if (a[i] == a[j]) i = j = -1; cout << i << " " << j << "\n"; } cout << "\n"; return; } void init() { lg2[0] = -1; for (int i = 1; i < lg2.size(); i++) lg2[i] = lg2[i / 2] + 1; lgN = lg2.back(); return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); init(); int TC; for (cin >> TC; TC; TC--) solve(); return 0; }

5|0E. Klever Permutation


一个神秘的构造题,简单来说就是要求任意长度为k的子区间的和之差不超过1,这样的话实际上也就是要要求相邻区间的变化应该是加一或减一这样的,因此我们可以规定奇数位为加1,这样分别从两端开始填入就好

#include<bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using i128 = __int128; using ldb = long double; #define int i64 using vi = vector<int>; using pii = pair<int, int>; using vii = vector<pii>; const int inf = INT_MAX, INF = 1e18; const int mod = 998244353; const vi dx = {0, 0, 1, -1}, dy = {1, -1, 0, 0}; using edge = array<int, 3>; int power(int x, int y) { int ans = 1; while (y) { if (y & 1) ans = ans * x % mod; x = x * x % mod, y /= 2; } return ans; } int inv(int x) { return power(x, mod - 2); } void solve() { int n, k, m; cin >> n >> k; vi res(n + 1); int l = 1, r = n; for (int i = 1; i <= k; i++) { for (int j = i; j <= n; j += k) { if (i & 1) res[j] = l++; else res[j] = r--; } } for( int i = 1 ; i <= n ; i ++ ) cout << res[i] << " "; cout << "\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int TC; for (cin >> TC; TC; TC--) solve(); return 0; }

6|0F. Feed Cats


首先我们定义f[i]表示只在区间[1,i]中喂猫的最优解。那么答案就是f[n].

考虑转移,如果位置i不喂猫,则f[i]=f[i1].如果当前位置喂猫,则需要求出来当前能喂的猫的数量k以及,当前所有能喂的猫的活动区间左端点的最小值l,则f[i]=f[l1]+k.

显然求l,k是我们要解决的问题。

首先用a[l]记录所有活动范围左端点为l的猫的活动范围的右端点。然后用multiset<int> v维护当前点能喂养所有猫活动范围的左端点。则k=v.size() , l = *v.begin().这样的话,每次只要新到达一个点向v中插入a[i].size()i,并且向now[a[i]]中插入i表示即可.然后当要离开当前点时,now[i]记录了哪些区间已经到达了有端点,在v中删掉即可。

#include<bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using i128 = __int128; using ldb = long double; #define int i64 using vi = vector<int>; using pii = pair<int, int>; using vii = vector<pii>; const int inf = 1e9, INF = 1e18; const int mod = 998244353; const vi dx = {0, 0, 1, -1}, dy = {1, -1, 0, 0}; void solve() { int n, m; cin >> n >> m; vector<vi> a(n + 1), now(n + 1); multiset<int> v; vi f(n + 1); for (int l, r; m; m--) cin >> l >> r, a[l].push_back(r); for (int i = 1, x; i <= n; i++) { for (auto j: a[i]) v.insert(i), now[j].push_back(i); if (v.empty()) x = 1; else x = *v.begin(); f[i] = max(f[i - 1], f[x - 1] + (int) v.size()); for (auto j: now[i]) v.erase(v.find(j)); } cout << f.back() << "\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int t; cin >> t; while (t--) solve(); return 0; }

当然我也看到了一些做法,通过预处理后缀最小值,加dp来计算l,k的方法.

7|0G. Moving Platforms


本质还是求最短路

假设走到u最短用时d,需要等待x时刻才能使得lu=lv,则从u走到v所需要的时间就是x+1

要求x,等价于下式

lu+d×su+x×sulv+d×sv+x×sv(modH)(susv)×xlvlu+d×(svsu)(modH)

也就是解一元线性同余方程的最小正整数解,解出x后也就知道边权了

#include<bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; using i128 = __int128; using ldb = long double; #define int i64 using vi = vector<int>; using pii = pair<int, int>; using vii = vector<pii>; const int inf = 1e9, INF = 1e18; const int mod = 998244353; const vi dx = {0, 0, 1, -1}, dy = {1, -1, 0, 0}; int exgcd(int a, int b, int &x, int &y) { if (b == 0) { x = 1, y = 0; return a; } int d = exgcd(b, a % b, y, x); y -= x * (a / b); return d; } int calc(int a, int b, int m) { int x, y, d, t; a = (a % m + m) % m, b = (b % m + m) % m; d = exgcd(a, m, x, y); if (b % d) return -1; x = x * b / d % (m / d); if (x < 0) x += m / d; return x; } void solve() { int n, m, H; cin >> n >> m >> H; vi l(n + 1), s(n + 1); for (int i = 1; i <= n; i++) cin >> l[i]; for (int i = 1; i <= n; i++) cin >> s[i]; vector<vi> e(n + 1); for (int u, v; m; m--) { cin >> u >> v; e[u].push_back(v); e[v].push_back(u); } vi dis(n + 1, -1); priority_queue<pii, vector<pii>, greater<pii>> q; q.emplace(0, 1); while (not q.empty()) { auto [d, u] = q.top(); q.pop(); if (dis[u] != -1) continue; dis[u] = d; for (int x; auto v: e[u]) { int B = ((l[v] + d % H * s[v]) % H - (l[u] + d % H * s[u]) % H + H) % H; int A = (s[u] - s[v] + H) % H; x = calc(A, B, H); if (x == -1) continue; q.emplace(d + x + 1, v); } } if (dis[n] == inf) cout << "-1\n"; else cout << dis[n] << "\n"; return; } i32 main() { ios::sync_with_stdio(false), cin.tie(nullptr); int t; cin >> t; while (t--) solve(); return 0; }

__EOF__

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