Codeforces 969 div2[A~E] 个人题解

2024-08-31 15:36

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

目录

A - Dora's Set

原题链接

思路分析

AC代码

B - Index and Maximum Value

原题链接

思路分析

AC代码

C - Dora and C++

原题链接

思路分析

AC代码

D - Iris and Game on the Tree

原题链接

思路分析

AC代码

E - Iris and the Tree

原题链接

思路分析

AC代码



A - Dora's Set

原题链接

A - Dora's Set

思路分析


显然不能选两个偶数

比较简单的结论:
任意相邻的两个数一定互质

任意相邻的两个奇数一定互质

于是得出:

那么两个奇数 中间 夹一个偶数一定合法,并且这样得到的三元组是最多的

时间复杂度:O(N),当然可以做到O(1)

AC代码

#include <bits/stdc++.h>using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;
constexpr int P = 1'000'000'007;void solve() {int l, r;std::cin >> l >> r;int res = 0;for (int i = l & 1 ? l : l + 1; i + 1 < r; i += 4) {++ res;}std::cout << res << '\n';
}int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);int t = 1;std::cin >> t;while (t--) {solve();}return 0;
}

B - Index and Maximum Value

原题链接

B - Index and Maximum Value

思路分析

我们注意到一个事情,由于每次操作都是对值域内的元素操作

那么从始至终,我们数组最大元素的下标始终不变(自己手玩一下就明白了)

时间复杂度:O(N)

AC代码

#include <bits/stdc++.h>using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;
constexpr int P = 1'000'000'007;void solve() {int n, m;std::cin >> n >> m;std::vector<int> a(n);for (int i = 0; i < n; ++ i) std::cin >> a[i];int ma = *std::max_element(a.begin(), a.end());for (int i = 0; i < m; ++ i) {char op;int l, r;std::cin >> op >> l >> r;if (l <= ma && ma <= r)ma += op == '+' ? 1 : -1;std::cout << ma << " \n"[i + 1 == m];}}int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);int t = 1;std::cin >> t;while (t--) {solve();}return 0;
}

C - Dora and C++

原题链接

C - Dora and C++

思路分析

根据裴蜀定理:给定x,y存在ax + by = gcd(x, y)

那么我们可以实现对每个元素任意次 gcd(a, b) 加减操作

那么我们一定可以将原数组的元素都调整到 [0, gcd(a, b)) 内

显然我们可以得到的 range 不会超过 gcd(a, b)

我们将调整后的数组排序,枚举最小值 c[i]

为什么最小值可以取原数组的元素?

因为任意最优解我们都可以通过整个数组加减gcd来使得其最小值落在[0, gcd(a, b))内

那么枚举最小值后,最大值是哪个?

对于最小值c[i],最大值一定是c[i - 1] + gcd

很明显,不做证明

时间复杂度:O(NlogN)

AC代码

#include <bits/stdc++.h>using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;
constexpr int P = 1'000'000'007;void solve() {int n, a, b;std::cin >> n >> a >> b;int g = std::gcd(a, b);std::vector<int> c(n);for (int i = 0; i < n; ++ i) std::cin >> c[i], c[i] %= g;std::ranges::sort(c);int res = c[n - 1] - c[0];for (int i = 1; i < n; ++ i) {res = std::min(res, c[i - 1] + g - c[i]);}std::cout << res << '\n';
}int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);int t = 1;std::cin >> t;while (t--) {solve();}return 0;
}

D - Iris and Game on the Tree

原题链接

D - Iris and Game on the Tree

思路分析

看起来很复杂,我们不妨先考虑比较好想的情况:根节点值确定

那么我们 Iris 一定将叶子尽可能染成和树根相反的值,Dora 一定尽可能将叶子染成和树根相同的值

记叶子中原来0的数目为c0,1的数目为c1,?为none

那么当root = 0时,Iris的收益就是 (none + 1) / 2 + c1

root=1不再赘述

当根节点值不确定:

这个时候我们发现,如果Iris先手调根,那么不管调几,Dora总能让Iris的收益减少

所以Iris要晚调根,同样的,Dora也要晚调根

那么当非叶子结点存在 ?时,二者都会先去调这些结点

这些结点数目的奇偶性决定了二者谁先手调根

所以我们分为两种情况,Iris先手调根:收益就是 max(c0, c1) + none / 2

当 可以使Dora先手的时候,收益是:min(c0, c1) + (none + 1) / 2

第二种情况可以取的时候需要和第一种情况取max

时间复杂度:O(N)

AC代码

#include <bits/stdc++.h>using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;
constexpr int P = 1'000'000'007;void solve() {int n;std::cin >> n;std::vector<int> d(n);for (int i = 1, u, v; i < n; ++ i) {std::cin >> u >> v;-- u, -- v;++ d[u], ++ d[v];}std::string s;std::cin >> s;int c0 = 0, c1 = 0, f = 0, none = 0;for (int i = 1; i < n; ++ i) {if (d[i] == 1) {if (s[i] == '0') ++ c0;else if(s[i] == '1') ++ c1;else ++ none;}else if (s[i] == '?') {f ^= 1;}}if (s[0] == '?') {int res = std::max(c0, c1) + none / 2;if (f)res = std::max(res, std::min(c0, c1) + (none + 1) / 2);std::cout << res << '\n';}else {if (s[0] == '1') std::cout << c0 + (none + 1) / 2 << '\n';else       std::cout << c1 + (none + 1) / 2 << '\n';}
}int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);int t = 1;std::cin >> t;while (t--) {solve();}return 0;
}

E - Iris and the Tree

原题链接

E - Iris and the Tree

思路分析

对于每个path,其收益为 w - 路径外已经确定的边权和

但是要进行特判:如果路径上边全部确定,那么其值就是路径权值和

然后可以注意到每条边在所有路径中一共出现两次

初始时,收益为n * w

最一般的情况:后面每增加一条边,除了该边出现的两条路径,所有的路径的值都会- 2f

如果考虑已经满了的路径,我们发现我们的收益就是:

已满路径的带权长度和 + 未满路径条数 * (w - 已出现路径长度和) + Σ未满路径上已出现的边权和

那么对于一条边<p[u], u>如何找到两条路径的端点?

u - 1 和 u所在子树最大dfs序,第二个我们逆着dfs序进行递推即可

由于给的是dfs序,lca(i, (i + 1) % n) = fa(i + 1),所以我们可以很容易处理出每条路径的边的数目

时间复杂度:O(N)

AC代码

#include <bits/stdc++.h>using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;
constexpr int P = 1'000'000'007;void solve() {int n;i64 w;std::cin >> n >> w;std::vector<int> p(n), d(n), res(n), submax(n);std::vector<std::vector<int>> adj(n);for (int i = 1; i < n; ++ i) {std::cin >> p[i], -- p[i];adj[p[i]].push_back(i);}for (int u = 0; u < n; ++ u)for (int v : adj[u])d[v] = d[u] + 1;for (int i = 0; i + 1 < n; ++ i) res[i] = d[i] + d[i + 1] - d[p[i + 1]] * 2;res[n - 1] = d[n - 1];std::iota(submax.begin(), submax.end(), 0);for (int i = n - 1; i; -- i)submax[p[i]] = std::max(submax[i], submax[p[i]]);std::vector<i64> len(n);i64 ans = 0, sum = 0, o = 0;int cnt = 0;for (int i = 1, v; i < n; ++ i) {i64 t;std::cin >> v >> t;-- v;int u = v - 1, sub = submax[v];sum += t;len[u] += t, len[sub] += t;o += 2 * t;if (!-- res[u]) {ans += len[u];o -= len[u];++ cnt;}if (! -- res[sub]) {ans += len[sub];o -= len[sub];++ cnt;}std::cout << ans + (n - cnt) * (w - sum) + o << " \n"[i + 1 == n];}}int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);int t = 1;std::cin >> t;while (t--) {solve();}return 0;
}

这篇关于Codeforces 969 div2[A~E] 个人题解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

Codeforces Round #261 (Div. 2)小记

A  XX注意最后输出满足条件,我也不知道为什么写的这么长。 #define X first#define Y secondvector<pair<int , int> > a ;int can(pair<int , int> c){return -1000 <= c.X && c.X <= 1000&& -1000 <= c.Y && c.Y <= 1000 ;}int m

Codeforces Beta Round #47 C凸包 (最终写法)

题意慢慢看。 typedef long long LL ;int cmp(double x){if(fabs(x) < 1e-8) return 0 ;return x > 0 ? 1 : -1 ;}struct point{double x , y ;point(){}point(double _x , double _y):x(_x) , y(_y){}point op

Codeforces Round #113 (Div. 2) B 判断多边形是否在凸包内

题目点击打开链接 凸多边形A, 多边形B, 判断B是否严格在A内。  注意AB有重点 。  将A,B上的点合在一起求凸包,如果凸包上的点是B的某个点,则B肯定不在A内。 或者说B上的某点在凸包的边上则也说明B不严格在A里面。 这个处理有个巧妙的方法,只需在求凸包的时候, <=  改成< 也就是说凸包一条边上的所有点都重复点都记录在凸包里面了。 另外不能去重点。 int

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

Codeforces 482B 线段树

求是否存在这样的n个数; m次操作,每次操作就是三个数 l ,r,val          a[l] & a[l+1] &......&a[r] = val 就是区间l---r上的与的值为val 。 也就是意味着区间[L , R] 每个数要执行 | val 操作  最后判断  a[l] & a[l+1] &......&a[r] 是否= val import ja

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

HomeBank:开源免费的个人财务管理软件

在个人财务管理领域,找到一个既免费又开源的解决方案并非易事。HomeBank&nbsp;正是这样一个项目,它不仅提供了强大的功能,还拥有一个活跃的社区,不断推动其发展和完善。 开源免费:HomeBank 是一个完全开源的项目,用户可以自由地使用、修改和分发。用户友好的界面:提供直观的图形用户界面,使得非技术用户也能轻松上手。数据导入支持:支持从 Quicken、Microsoft Money

C - Word Ladder题解

C - Word Ladder 题解 解题思路: 先输入两个字符串S 和t 然后在S和T中寻找有多少个字符不同的个数(也就是需要变换多少次) 开始替换时: tips: 字符串下标以0开始 我们定义两个变量a和b,用于记录当前遍历到的字符 首先是判断:如果这时a已经==b了,那么就跳过,不用管; 如果a大于b的话:那么我们就让s中的第i项替换成b,接着就直接输出S就行了。 这样

分布式系统的个人理解小结

分布式系统:分的微小服务,以小而独立的业务为单位,形成子系统。 然后分布式系统中需要有统一的调用,形成大的聚合服务。 同时,微服务群,需要有交流(通讯,注册中心,同步,异步),有管理(监控,调度)。 对外服务,需要有控制的对外开发,安全网关。