Codeforces Global Round 26 A~E

2024-06-16 15:12
文章标签 codeforces global round 26

本文主要是介绍Codeforces Global Round 26 A~E,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

A.Strange Splitting(思维)

题意:

将非空数组的范围定义为最大值减去最小值。例如, [ 1 , 4 , 2 ] [1,4,2] [1,4,2]的范围是 4 − 1 = 3 4-1=3 41=3

给你一个长度为 n ≥ 3 n\geq 3 n3的数组 a 1 , a 2 , … , a n a_1,a_2,\ldots,a_n a1,a2,,an保证 a a a被排序

你必须给 a a a中的每个元素涂上红色或蓝色,以便:

  • 红色元素的范围不等于蓝色元素的范围,并且
  • 每种颜色至少有一个元素。

如果不存在这样的着色,则输出 N O NO NO。如果存在多种有效着色,则可以输出其中任何一种。

分析:

如果 a 1 = a n a_1=a_n a1=an,无解。

如果 a 2 = a n a_2=a_n a2=an a 1 , a 2 a_1,a_2 a1,a2涂成红色,否则只把 a 1 a_1 a1涂成红色。

代码:

#include<bits/stdc++.h>using namespace std;
const int N = 1e6 + 10;
int a[N];void solve() {int n;cin >> n;for (int i = 1; i <= n; ++i)cin >> a[i];if (a[1] == a[n]) {cout << "NO" << endl;return;}cout << "YES" << endl;if (a[2] != a[n]) {cout << "R";for (int i = 2; i <= n; ++i) {cout << "B";}cout << endl;return;}cout << "RR";for (int i = 3; i <= n; ++i) {cout << "B";}cout << endl;
}int main() {int t;cin >> t;while (t--)solve();return 0;
}

B.Large Addition(模拟)

题意:

如果一个数位介于 5 5 5 9 9 9之间(含),则该数位为大数。如果一个正整数的所有位数都是大数,那么这个正整数就是大正整数。

给你一个整数 x x x。它可以是两个位数相同的大正整数之和吗?

分析:

由于大于等于 5 5 5小于等于 9 9 9的数不管这么组合,两个数字相加的和一定在 10 − 18 10-18 1018之间,那么可以得到如果给出的数的第一位上不是 1 1 1或者最后一位上是 9 9 9或者或者中间有一位上是 0 0 0,那么就是不存在的,否则就是可行的。

代码:

#include<bits/stdc++.h>typedef long long LL;
using namespace std;void solve() {LL x;cin >> x;bool flag = 1;if (x % 10 == 9)flag = 0;x /= 10;while (x) {int y = x % 10;if ((y + 9) % 10 == 9)flag = 0;if (x < 10 && y > 1)flag = 0;x /= 10;}if (flag)cout << "YES" << endl;elsecout << "NO" << endl;
}int main() {int t;cin >> t;while (t--)solve();return 0;
}

C1.Magnitude (Easy Version)(贪心)

题意:

两个版本的问题是不同的。

给你一个长度为 n n n的数组 a a a。从 c = 0 c=0 c=0开始。然后,对于从 1 1 1 n n n的每一个 i i i(按递增顺序)做下面的操作之一

  • 选项 1 1 1: 设置 c c c c + a i c+a_i c+ai
  • 选项 2 2 2: 设置 c c c ∣ c + a i ∣ |c+a_i| c+ai ∣ x ∣ |x| x x x x的绝对值。

设上述步骤后 c c c的最大终值等于 k k k。求出 k k k

分析:

发现要么一直不用 2 2 2操作,要么在答案取到最小值的时候使用一遍 2 2 2操作让其变为相对大一些的值。显然使用多遍 2 2 2操作是不优的。然后还能发现若存在一个位置 P P P使得前缀和小于 0 0 0,那么这个地方实验 2 2 2操作较优。因此若不存在一个前缀和的值小于 0 0 0那么就不应该使用 2 2 2操作。否则一定在任意一个值最小的位置使用一次 2 2 2操作即可。

代码:

#include<bits/stdc++.h>typedef long long LL;
using namespace std;
const int N = 1e6 + 10;
LL a[N], pre[N];void solve() {LL n, id = -1;cin >> n;for (LL i = 1; i <= n; i++) {cin >> a[i];pre[i] = pre[i - 1] + a[i];}LL mi = 0;for (LL i = n; i; i--) {if (pre[i] < mi) {mi = pre[i];id = i;}}if (id == -1)cout << pre[n] << endl;else {LL s = 0;for (LL i = 1; i <= n; i++) {if (i <= id)s -= a[i];elses += a[i];}cout << s << endl;}
}int main() {int t;cin >> t;while (t--)solve();return 0;
}

C2.Magnitude (Hard Version)(贪心)

题意:

两个版本的问题是不同的。

给你一个长度为 n n n的数组 a a a。从 c = 0 c=0 c=0开始。然后,对于从 1 1 1 n n n的每个 i i i(按递增顺序),做以下操作之一

  • 选项 1 1 1:设置 c c c c + a i c+a_i c+ai
  • 选项 2 2 2:设置 c c c ∣ c + a i ∣ |c+a_i| c+ai ∣ x ∣ |x| x x x x的绝对值。

假设经过上述程序后, c c c的最大终值等于 k k k。求得出 c = k c=k c=k的唯一程序的个数。如果在任意索引 i i i处,一个程序选择了选项 1 1 1,而另一个程序选择了选项 2 2 2,即使 c c c的值在该轮之后对两个程序都相等,那么这两个程序也是不同的。

由于答案可能很大,输出对 998244353 998244353 998244353取模的结果。

分析:

每一步结束之后,若当前的前缀和取到了全部前缀和的最小值,则这一步对答案造成了 2 n − i + r 2^{n-i+r} 2ni+r贡献,其中 r r r是在这一步操作中前缀和不小于 0 0 0的位置的数量。若全部操作中没有任何一个前缀和小于 0 0 0则答案为 2 n 2^n 2n

不存在任何一个前缀和使得这个前缀和不大于 0 0 0。此时对于任意一个位置 1 1 1操作和 2 2 2操作没有任何本质区别。任意一步都可以在 1 1 1操作和 2 2 2操作中任选一个操作执行。

存在一个前缀和使得这个前缀和不大于 0 0 0。因为执行完这一步之后后面不论怎么走答案都不会偏离最大值(参见 C 1 C1 C1的结论),所以说后面的任意一步都可以在 1 1 1操作和 2 2 2操作中任选,即 2 n − i 2^{n-i} 2ni种不同选择;若前面有前缀和大于等于 0 0 0的那么 1 1 1操作和 2 2 2操作没有本质的区别,若有 r r r个满足这样条件的则有 2 r 2^r 2r种不同选择。根据乘法原理可知对答案的贡献为 2 n − i + r 2^{n-i+r} 2ni+r。其中 r r r可以在枚举的时候扫一遍得出答案。

代码:

#include<bits/stdc++.h>typedef long long LL;
using namespace std;
const int N = 1e6 + 10;
const int MOD = 998244353;
LL a[N], pre[N], bin[N];void solve() {int n;cin >> n;for (int i = 1; i <= n; i++) {cin >> a[i];pre[i] = pre[i - 1] + a[i];}LL mi = 0, r = 0;for (int i = 1; i <= n; i++)mi = min(mi, pre[i]);if (mi == 0)cout << bin[n] << endl;else {int ans = 0;for (int i = 1; i <= n; i++) {if (pre[i] >= 0)r++;if (pre[i] == mi)ans = (ans + bin[n - i + r]) % MOD;}cout << ans << endl;}
}int main() {int t;cin >> t;bin[0] = 1;for (int i = 1; i < N; i++)bin[i] = bin[i - 1] * 2 % MOD;while (t--)solve();return 0;
}

D.“a” String Problem(数学)

题意:

给你一个由小写拉丁字符组成的字符串 s s s。请计算非空字符串 t ≠ t\neq t=" a \texttt{a} a"的个数。使得可以将 s s s分割为满足以下条件的一些子字符串:

  • 每个子串要么等于 t t t要么等于" a \texttt{a} a",并且
  • 至少有一个子串等于 t t t

† ^{\dagger} 字符串 s s s的分区是由一些 k k k字符串 t 1 , t 2 , … , t k t_1,t_2,\ldots,t_k t1,t2,,tk(称为子串)组成的有序序列,使得 t 1 + t 2 + … + t k = s t_1+t_2+\ldots+t_k=s t1+t2++tk=s,其中 + + +表示连接操作。

分析:

s s s长度为 n n n。特判全为 a a a的情况,共 n − 1 n−1 n1种方案。

s s s中非 a a a字符的数量为 m m m

如果 t t t中有 k k k个非 a a a字符,把 t t t掐头去尾忽略前后的 a a a后,原串里一定恰好存在 m k \frac{m}{k} km t ′ t′ t,且 k ∣ m k∣m km

枚举 k k k。记录第 i i i个非 a a a字符的位置为 p i p_i pi(从 0 0 0开始),如果 s p i ≠ s p i − k s_{p_i} \neq s_{p_i−k} spi=spik或不在分割处的 p i − p i − 1 ≠ p i − k − p i − k − 1 p_i−p_{i−1}\neq p_{i−k}−p_{i−k−1} pipi1=pikpik1 t ′ t′ t不合法。

t ′ t′ t还原为 t t t,枚举左边有的 a a a个数 l ∈ [ 0 , p 0 ] l∈[0,p_0] l[0,p0]

x x x为分割处的最小间隔 m i n ( p i − p i − 1 ) min(p_i−p_{i−1}) min(pipi1) k ∣ i k∣i ki,则右边的 a a a个数 r ∈ [ 0 , m i n ( x − l , n − p m − 1 − 1 ) ] r∈[0,min(x−l,n−p_{m−1}-1)] r[0,min(xl,npm11)]

代码:

#include<bits/stdc++.h>typedef long long LL;
using namespace std;
const int MOD = 998244353;void solve() {string s;cin >> s;int n = s.length();if (count(s.begin(), s.end(), 'a') == n) {cout << n - 1 << endl;return;}vector<int> a;for (int i = 0; i < n; ++i) {if (s[i] != 'a') {a.emplace_back(i);}}int m = a.size();LL ans = 0;for (int i = 1; i <= m; ++i) {if (m % i) {continue;}int ok = 1;for (int j = i; j < m; ++j) {int o = j % i;if (s[a[j]] != s[a[o]] || (o && a[o] - a[o - 1] != a[j] - a[j - 1])) {ok = 0;break;}}if (ok) {int mi = n;for (int j = i; j < m; j += i) {mi = min(mi, a[j] - a[j - 1] - 1);}int r = n - a.back() - 1;for (int l = 0; l <= a[0]; ++l) {ans += max(0, min(r + 1, mi - l + 1));}}}cout << ans << endl;
}int main() {int t;cin >> t;while (t--)solve();return 0;
}

E.Shuffle(树形DP)

题意:

两只饥饿的小熊猫奥斯卡和卢拉有一棵有 n n n个节点的树 T T T。它们愿意在整棵树 T T T精确地执行一次下面的洗牌程序。通过这个洗牌过程,他们将从旧树的节点中创建一棵新树。

  1. 从原始树 T T T中选择任意一个节点 V V V。创建一棵以 V V V为根的新树 T 2 T_2 T2
  2. T T T中移除 V V V,这样原树就会分裂成一个或多个子树(如果 V V V T T T中的唯一节点,则子树数量为零)。
  3. 用同样的方法对每棵子树进行洗牌(同样选择任意节点作为根节点),然后将所有洗牌后子树的根节点连接回 V V V以完成 T 2 T_2 T2的构建。

这样,奥斯卡和卢拉就得到了一棵新树 T 2 T_2 T2。它们只能吃树叶,而且非常饥饿,因此请找出在所有树中,只需一次洗牌就能生成的树叶的最大数量。

请注意,树叶是阶数为 1 1 1的所有节点。因此,如果树根只有一个子节点,那么它就可以被视为树叶。

分析:

把一个点的父亲儿子都加到 T 2 T_2 T2后,这个点就是叶子,且与之直接相连的点都不是叶子。(所有相邻点都是这个点的祖先)。

所有的叶子构成一个独立集,我们找去除根后最大的。

枚举每个节点作为初始的根,换根进行 d p dp dp。如果根本身就是叶子还要在加一。

具体来说,第一次扫描以 1 1 1为根求出 f x , 1 / 0 f_{x,1/0} fx,1/0表示以 x x x为根的子树中 x x x选/不选的最大独立集:
{ f x , 0 = ∑ y ∈ g x max ⁡ ( f y , 0 , f y , 1 ) f x , 1 = ∑ y ∈ g x f y , 0 \begin{cases}f_{x,0}=\sum_{y\in g_x}\max(f_{y,0},f_{y,1})\\f_{x,1}=\sum_{y\in g_x}f_{y,0}\end{cases} {fx,0=ygxmax(fy,0,fy,1)fx,1=ygxfy,0

第二次扫描求出 h x , 1 / 0 h_{x,1/0} hx,1/0表示选/不选 x x x的最大独立集,
h 1 , 0 / 1 = f 1 , 0 / 1 h_{1,0/1}=f_{1,0/1} h1,0/1=f1,0/1 { h x , 0 = max ⁡ ( h f a , 1 , f x , 0 + ( h f a , 0 − max ⁡ ( f x , 1 , f x , 0 ) ) ) h x , 1 = f x , 1 + ( h f a , 0 − max ⁡ ( f x , 1 , f x , 0 ) ) \begin{cases}h_{x,0}=\max(h_{fa,1},f_{x,0}+(h_{fa,0}-\max(f_{x,1},f_{x,0})))\\h_{x,1}=f_{x,1}+(h_{fa,0}-\max(f_{x,1},f_{x,0}))\end{cases} {hx,0=max(hfa,1,fx,0+(hfa,0max(fx,1,fx,0)))hx,1=fx,1+(hfa,0max(fx,1,fx,0))

h x , 0 + [ x is leaf ] h_{x,0}+[x \texttt{ is leaf}] hx,0+[x is leaf]更新答案。

代码:

#include<bits/stdc++.h>using namespace std;
const int MOD = 998244353;void solve() {int n;cin >> n;vector<vector<int>> g(n + 1);for (int i = 1; i < n; ++i) {int x, y;cin >> x >> y;g[x].emplace_back(y);g[y].emplace_back(x);}vector<array<int, 2>> f(n + 1, {0, 0});auto dfs = [&](auto &&dfs, int x, int fa) -> void {f[x][0] = 0;f[x][1] = 1;for (int y: g[x]) {if (y != fa) {dfs(dfs, y, x);f[x][0] += max(f[y][0], f[y][1]);f[x][1] += f[y][0];}}};dfs(dfs, 1, 0);vector<array<int, 2>> h(n + 1);h[1][0] = f[1][0];h[1][1] = f[1][1];int ans = h[1][0] + (g[1].size() == 1);auto dfs2 = [&](auto &&dfs2, int x, int fa) -> void {int tmp = h[fa][0] - max(f[x][0], f[x][1]);h[x][1] = f[x][1] + tmp;h[x][0] = max(h[fa][1], f[x][0] + tmp);tmp = h[x][0] + (g[x].size() == 1);ans = max(ans, tmp);for (int y: g[x]) {if (y != fa) {dfs2(dfs2, y, x);}}};for (int y: g[1]) {dfs2(dfs2, y, 1);}cout << ans << endl;
}int main() {int t;cin >> t;while (t--)solve();return 0;
}

赛后交流

在比赛结束后,会在交流群中给出比赛题解,同学们可以在赛后查看题解进行补题。

群号: 704572101,赛后大家可以一起交流做题思路,分享做题技巧,欢迎大家的加入。

这篇关于Codeforces Global Round 26 A~E的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1066790

相关文章

Codeforces 158B

很久没有刷题了,刚刚有小学弟问了这道题,AC之后贴上来吧。水~~~ #include <cstdio>#include <cmath>int main() {int n;while(scanf("%d", &n) != EOF) {int a = 0, b = 0, c = 0, d = 0;int arr[100001];for (int i = 0; i < n; ++

Codeforces April Fools Day Contest 2014(附官方题解)

Codeforces2014年愚人节的坑题。。。但还是感觉挺好玩的。。。 A. The Great Game time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Two teams mee

Codeforces April Fools Day Contest 2013

2013年愚人节的坑题。。。 A. Mysterious strings time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Input The input contains a sin

什么是慢查询——Java全栈知识(26)

1、什么是慢查询 慢查询:也就是接口压测响应时间过长,页面加载时间过长的查询 原因可能如下: 1、聚合查询 2、多表查询 3、单表数据量过大 4、深度分页查询(limit) 如何定位慢查询? 1、Skywalking 我们可以通过 Skywalking 来看到是哪个请求的哪个查询的时间执行时间过长。 2、Mysql 自带的慢日志查询 慢查询日志记录了所有执行时间超过指定参数(long

【Rust日报】 2019-03-26

Sonic 这是一个牛逼的库,故而再发一次。很多人说过,Rust 在大数据领域其实是一个很有潜力的竞争者,但是在被 Java/C++ 垄断的领域,后来者 Rust 如何能在已经非常成熟的这个领地抢占吞噬一块自己的根据地。只能靠两点了: 高性能。同等数据量的情况下,速度提高一倍到数十倍;低内存占用。同等数据量的情况下,内存占用少数十倍。 而 Sonic 就是这样一个可以逐渐替换 Elasticse

【Rust日报】 2019-05-26:切片索引检查导致的3倍性能下降问题一例

漫游 Tox-rs,第一部分 长文预警。Tox 是一个分布式的P2P,加密传输,易于使用的基于DHT的网络。 Tox 原来是个C项目,作者用Rust通过审视发现,实现里面有不少漏洞,易被攻击。所以他用Rust重写了它。就是上面那个项目地址。现在作者,开始整理这几年的工作,开始生成文档。 Read More 切片索引检查导致的3倍性能下降问题一例 作者发现下面这两片代码: pub fn

【Rust日报】2020-10-26 Box 即将支持自定义的 allocators

Box 即将支持自定义的 allocators 下面的 pull request 合并之后, Box 将会支持自定义的 allocators. Box 的定义将会从 Box<T> 变成 Box<T, A = Global>. https://github.com/rust-lang/rust/pull/77187 Rust 的 Hyper 会让 Curl 变的更安全 curl 是使用 C 语言编

【Rust日报】2021-01-26 太素桌面系统:基于RISC-V架构的Rust系统内核

太素桌面系统:基于RISC-V架构的Rust系统内核(十二) 编写“太素”桌面操作系统的文章更新到第十二期。本期文章在前文成果的基础上,开始编写一个简单的桌面系统结构。这包括桌面、窗口和其中的控件,以及文字标签的显示方式。 太素OS是一个RISC-V架构、Rust编写的操作系统内核。作者在系列文章中介绍,“太素”的名字来源于道家五太之一,可以演化万物。这个项目实现了包含图形处理器在内的外部设备控

【Rust 日报】2021-11-21 The RustFest Global - Rust in Arts

RustFest Global 2021:Rust In Arts Edition 日程:(https://rustfest.global/schedule/ 地址:https://watch.rustfest.global/ pigeon-rs:电子邮件自动化工具 Pigeon 是一种命令行工具,用于以廉价且高效的方式自动化电子邮件工作流程。 比如,查询时事通讯的订阅者并向他们发送电子邮件:

【第26章】Vue实战篇之用户信息修改

文章目录 前言一、界面搭建1. UserInfo.vue 二、更新用户信息1.绑定用户信息2.更新接口3.更新事件3.1 添加事件3.2 触发事件 总结 前言 这里来学习用户信息的修改。 一、界面搭建 1. UserInfo.vue <script setup>import { ref } from 'vue'const userInfo = ref({id: