比赛链接

A

题解

知识点:贪心。

考虑两种方法:

  1. 所有不同的位置使用操作1变成相同
  2. 使用操作1将两串01数量相同,然后使用1次操作2

取其中最小的即可。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

  1. #include <bits/stdc++.h>
  2. #define ll long long
  3. using namespace std;
  4. int a[107], b[107];
  5. bool solve() {
  6. int n;
  7. cin >> n;
  8. for (int i = 1;i <= n;i++) cin >> a[i];
  9. for (int i = 1;i <= n;i++) cin >> b[i];
  10. int cnt1 = 0;
  11. int cnt2 = 0;
  12. for (int i = 1;i <= n;i++) {
  13. cnt1 += a[i] != b[i];
  14. cnt2 += a[i] - b[i];
  15. }
  16. cout << min(cnt1, abs(cnt2) + 1) << '\n';
  17. return true;
  18. }
  19. int main() {
  20. std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  21. int t = 1;
  22. cin >> t;
  23. while (t--) {
  24. if (!solve()) cout << -1 << '\n';
  25. }
  26. return 0;
  27. }

B

题解

知识点:数论,贪心。

充要条件:存在 \(b\) ,当且仅当 \(gcd(a[i-1],a[i+1]) | a[i]\) 。

显然,如果存在 \(b\) 那么 \(b[i]\) 一定会包括 \(a[i-1]\) 和 \(a[i]\) 的因子,而 \(a[i] = gcd(b[i],b[i+1])\) 一定能被 \(gcd(a[i-1],a[i])\) 整除。

若 \(gcd(a[i-1],a[i+1]) | a[i]\) ,那么构造 \(b[i] = lcm(a[i],a[i-1])\) ,则:

\[\begin{aligned}
gcd(b[i],b[i+1]) &= gcd(lcm(a[i-1],a[i]),lcm(a[i],a[i+1])) \\
&= a[i] \cdot gcd\bigg(\frac{a[i-1]}{gcd(a[i-1],a[i])},\frac{a[i+1]}{gcd(a[i],a[i+1])}\bigg)
\end{aligned}
\]

注意到,因为 \(gcd(a[i-1],a[i+1])|a[i]\) ,因此 \(gcd(a[i-1],a[i])\) 一定包含 \(gcd(a[i-1],a[i+1])\) ,同理 \(gcd(a[i],a[i+1])\) 也是,因此 \(gcd\bigg(\dfrac{a[i-1]}{gcd(a[i-1],a[i])},\dfrac{a[i+1]}{gcd(a[i],a[i+1])}\bigg) = 1\) ,所以 \(gcd(b[i],b[i+1]) = a[i]\) ,存在 \(b\) 。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

  1. #include <bits/stdc++.h>
  2. #define ll long long
  3. using namespace std;
  4. int a[100007];
  5. bool solve() {
  6. int n;
  7. cin >> n;
  8. for (int i = 1;i <= n;i++) cin >> a[i];
  9. for (int i = 2;i <= n - 1;i++) {
  10. if (a[i] % __gcd(a[i - 1], a[i + 1])) return false;
  11. }
  12. cout << "YES" << '\n';
  13. return true;
  14. }
  15. int main() {
  16. std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  17. int t = 1;
  18. cin >> t;
  19. while (t--) {
  20. if (!solve()) cout << "NO" << '\n';
  21. }
  22. return 0;
  23. }

C1

题解

知识点:双指针,枚举。

对于区间内的一个位置 \(i\) ,当左端点 \(l\) 满足 \(i-a[i]+1\leq l\) 时,\(i\) 才能可能存在于 \(l\) 开始的区间。

同时,注意到区间端点具有单调性,即 \([l,r]\) 是一个合法区间,那么 \([i,r],i\in[l,r]\) 都是合法区间,因此可以尺取法枚举左端点 \(l\) ,找到第一个不可行右端点 \(r\) ,就直接得到从 \(l\) 为左端点的区间个数 \(r-l\) 。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

  1. #include <bits/stdc++.h>
  2. #define ll long long
  3. using namespace std;
  4. int a[200007];
  5. bool solve() {
  6. int n;
  7. cin >> n;
  8. for (int i = 1;i <= n;i++) cin >> a[i];
  9. int l = 1, r = 1;
  10. ll ans = 0;
  11. while (l <= n) {
  12. while (r <= n) {
  13. if (r + 1 - a[r] > l) break;
  14. r++;
  15. }
  16. ans += r - l;
  17. l++;
  18. }
  19. cout << ans << '\n';
  20. return true;
  21. }
  22. int main() {
  23. std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  24. int t = 1;
  25. cin >> t;
  26. while (t--) {
  27. if (!solve()) cout << -1 << '\n';
  28. }
  29. return 0;
  30. }

C2

题解

知识点:前缀和,双指针,枚举。

此题能用线段树二分做,但实际上二分查找右端点没有必要,可以尺取法中同时预处理出来。

先考虑修改 \(a[p]\) 到 \(x\) 会改变什么。如果 \(x > a[p]\) ,那么一些原本右端点被 \(p\) 阻挡的区间现在可能跨越 \(p\) 再往后走一段;如果 \(x<a[p]\) ,那么原本一些跨越了 \(p\) 的区间右端点现在可能会被 \(p\) 阻挡(\(\geq p\) 的不受影响接下来不讨论)。

明确了修改 \(a[p]\) 会导致的变化,那就开始具体讨论:

  1. \(x < a[p]\) ,我们首先需要知道跨越了 \(p\) 的具体区间是什么才能进行下一步操作。因为区间端点是单调的,我们只需要知道第一个右端点可以跨越 \(p\) 的左端点即可,那么到 \(p-1\) 为止的左端点都是可以跨越 \(p\) 的。

    我们在尺取法中扩展右端点时,用 \(Lr[r]\) 记录以 \(r\) 为右端点的左端点,由于每个 \(r\) 只会记录一次,那么 \(Lr[r]\) 一定代表第一次以 \(r\) 为右端点可行的左端点 \(l\) ,所以 \(Lr[p]\) 即区间右端点能跨越 \(p\) 的第一个左端点。

    接下来要考虑 \(a[p]\) 修改成 \(x\) 之后影响了左端点 \([Lr[p],p-1]\) 的哪一部分。显然, \(x\) 在位置 \(p\) 作为右端点时,左端点的可能范围是 \([p-x+1,p-1]\) 。那么只有在 \(p-x+1 > Lr[p]\) 时,才会使 \([Lr[p],p-x]\) 这些原本能跨越 \(p\) 的左端点的右端点被 \(p\) 阻挡,否则不会影响答案。

    因此,我们设前缀和 \(pre[i]\) 代表 \([1,i]\) 的点作为左端点产生的合法区间个数。我们先减去 \([Lr[p],p-x]\) 这部分左端点原本提供的区间个数,再加上新的个数,即 \(\sum_{i = Lr[p]}^{p-x} p-i = \dfrac{(p-Lr[p]+x)(p-x-Lr[p]+1)}{2}\) ,每个左端点 \(i\) 被 \(p\) 阻挡提供 \(p-i\) 个区间。所以最终答案为 \(pre[n] - (pre[p-x]-pre[Lr[p]-1]) + \dfrac{(p-Lr[p]+x)(p-x-Lr[p]+1)}{2}\) 。

  2. \(x>a[p]\) ,同样我们先确定右端点被 \(p\) 阻挡的左端点区间。我们只需要在每个左端点 \(l\) 扩展不了时,记录一下此时的 \(r\) ,即 \(Ll[r] = l\) 来表示被 \(r\) 阻挡的左端点,同时对于每个 \(r\) 只记录一次,因此 \(Ll[r]\) 就代表第一个被 \(r\) 阻挡的左端点。

    在上文提到 \(Lr[r]\) 代表第一个可以跨越 \(r\) 的左端点,那 \(Lr[r]-1\) 就是最后一个被 \(r\) 阻挡的左端点。于是, \([Ll[p],Lr[p]-1]\) 就是被 \(p\) 阻挡的左端点区间。

    注意到,可能出现不存在左端点会被 \(p\) 阻挡,这时候 \(Ll[p]\) 应为初始化的值 \(0\) ,答案不变。否则,被 \(p\) 阻挡的左端点区间必然存在。

    同时,如果存在这样的区间,那么 \(p-a[p]+1\) 必然等于 \(Lr[p]\) 。因此如果 \(x<a[p]\) ,那么 \(p-x+1\) 一定小于 \(Lr[p]\) ,一定会改变答案。 于是,需要修改答案的左端点区间就是 \([\max(Ll[p],p-x+1),Lr[p]-1]\) 。

    最后我们还需要知道,这些左端点跨越了 \(p\) 之后的右端点最多到哪。在一开始的尺取法时,我们用 \(rr\) 来记录,当 \(l\) 被 \(r\) 阻挡时,跨越 \(r\) 后又会被阻挡的位置,那么 \(rr-l\) 即 \(l\) 跨越 \(r\) 后的合法区间的新个数。

    我们同样用前缀和记录一下,\(skpre[i]\) 代表 \([1,i]\) 的区间的左端点,可以跨越一次阻挡自己的位置后的合法区间个数。我们先减去 \([\max(Ll[p],p-x+1),Lr[p]-1]\) 的原本的答案 \(pre[Lr[p]-1] - pre[\max(Ll[p],p-x+1)-1]\) ,再加上新的个数 \(skpre[Lr[p]-1] - skpre[\max(Ll[p],p-x+1)-1]\) 。 所以最终答案为 \(pre[n] - (pre[Lr[p]-1] - pre[\max(Ll[p],p-x+1)-1]) + (skpre[Lr[p]-1] - skpre[\max(Ll[p],p-x+1)-1])\)

时间复杂度 \(O(n+q)\)

空间复杂度 \(O(n)\)

代码

  1. #include <bits/stdc++.h>
  2. #define ll long long
  3. using namespace std;
  4. int a[200007];
  5. int Ll[200007], Lr[200007];
  6. ll pre[200007], skpre[200007];
  7. int main() {
  8. std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  9. int n;
  10. cin >> n;
  11. for (int i = 1;i <= n;i++) cin >> a[i];
  12. int l = 1, r = 1, rr = 1;//l为目前起点,r为以l为左端点的第一个不行的点,rr为跨越障碍点后第一个不行的点
  13. while (l <= n) {
  14. while (r <= n && r - a[r] + 1 <= l) Lr[r++] = l;//Lr[r]为r左边第一个可行l,即左边最后一个以r为障碍的点+1
  15. rr = min(max(rr, r + 1), n + 1);
  16. while (rr <= n && rr - a[rr] + 1 <= l) rr++;
  17. if (!Ll[r]) Ll[r] = l;//Ll[r]为r左边第一个不可行l
  18. pre[l] = pre[l - 1] + r - l;
  19. skpre[l] = skpre[l - 1] + rr - l;
  20. l++;
  21. }
  22. int q;
  23. cin >> q;
  24. while (q--) {
  25. ll ans = pre[n];
  26. int p, x;
  27. cin >> p >> x;
  28. if (x < a[p] && p - x + 1 > Lr[p]) {
  29. ans -= pre[p - x] - pre[Lr[p] - 1];
  30. ans += 1LL * (x + p - Lr[p]) * (p - x - Lr[p] + 1) / 2;
  31. }
  32. else if (x > a[p] && Ll[p]) {
  33. ans -= pre[Lr[p] - 1] - pre[max(p - x + 1, Ll[p]) - 1];
  34. ans += skpre[Lr[p] - 1] - skpre[max(p - x + 1, Ll[p]) - 1];
  35. }
  36. cout << ans << '\n';
  37. }
  38. return 0;
  39. }

D

题解

知识点:构造。

显然,\(1\) 或 \(0\) 的个数为奇数时一定不可能。

猜想,\(1\) 和 \(0\) 个数都为偶数时,一定能够造出。考虑两两构造成 \(s[i] = s[i+1]\) 的形式,如此只要取 \(i = 2k-1\) 即可。

当 \(s[i] = s[i+1]\) 时符合构造不需要修改,当 \(s[i] \neq s[i+1]\) 时考虑如下修改。

不符合我们构造形式的 \(01\) 组合一定是成对出现,比如 01 出现,因为 \(0\) 和 \(1\) 的个数都为偶数,那么一定会再出现一次 \(s[i] \neq s[i+1]\) 的组合来使个数为偶数。

我们考虑对第一个组合取出一个 \(0\) ,那么剩下一个 \(1\) ,需要从下一个组合取出一个 \(1\) 给这一组即可,那么下一组就会剩下一个 \(0\) ,再从下下一组取出一个 \(0\) ,以此类推。因为成对出现,所以取到最后一定取的是 \(1\) ,剩下一个 \(0\) ,那么把第一组取的 \(0\) 填上即可。

我们注意到上面取的过程,实际上就是右边一组往左边一组传递一个数字,第一组给最后一组传递一个数字,也就是题目给出的一次操作,于是就构造成功了。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

  1. #include <bits/stdc++.h>
  2. #define ll long long
  3. using namespace std;
  4. bool solve() {
  5. int n;
  6. string s;
  7. cin >> n >> s;
  8. if (count(s.begin(), s.end(), '1') & 1) return false;
  9. s = '?' + s;
  10. bool cur = 0;//cur代表上一组不同的缺的数字
  11. vector<int> b;
  12. for (int i = 1;i <= 2 * n;i += 2) {
  13. if (s[i] != s[i + 1]) {
  14. if (s[i] - '0' == cur) b.push_back(i), cur ^= 1;//取出上一组需要的数字,然后更换cur,往复循环
  15. else b.push_back(i + 1), cur ^= 1;
  16. }
  17. }
  18. cout << b.size() << ' ';
  19. for (auto i : b) cout << i << ' ';
  20. cout << '\n';
  21. for (int i = 1;i <= 2 * n;i += 2) cout << i << ' ';
  22. cout << '\n';
  23. return true;
  24. }
  25. int main() {
  26. std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  27. int t = 1;
  28. cin >> t;
  29. while (t--) {
  30. if (!solve()) cout << -1 << '\n';
  31. }
  32. return 0;
  33. }

Codeforces Round #825 (Div. 2) A-D的更多相关文章

  1. Codeforces Round #366 (Div. 2) ABC

    Codeforces Round #366 (Div. 2) A I hate that I love that I hate it水题 #I hate that I love that I hate ...

  2. Codeforces Round #354 (Div. 2) ABCD

    Codeforces Round #354 (Div. 2) Problems     # Name     A Nicholas and Permutation standard input/out ...

  3. Codeforces Round #368 (Div. 2)

    直达–>Codeforces Round #368 (Div. 2) A Brain’s Photos 给你一个NxM的矩阵,一个字母代表一种颜色,如果有”C”,”M”,”Y”三种中任意一种就输 ...

  4. cf之路,1,Codeforces Round #345 (Div. 2)

     cf之路,1,Codeforces Round #345 (Div. 2) ps:昨天第一次参加cf比赛,比赛之前为了熟悉下cf比赛题目的难度.所以做了round#345连试试水的深浅.....   ...

  5. Codeforces Round #279 (Div. 2) ABCDE

    Codeforces Round #279 (Div. 2) 做得我都变绿了! Problems     # Name     A Team Olympiad standard input/outpu ...

  6. Codeforces Round #262 (Div. 2) 1003

    Codeforces Round #262 (Div. 2) 1003 C. Present time limit per test 2 seconds memory limit per test 2 ...

  7. Codeforces Round #262 (Div. 2) 1004

    Codeforces Round #262 (Div. 2) 1004 D. Little Victor and Set time limit per test 1 second memory lim ...

  8. Codeforces Round #371 (Div. 1)

    A: 题目大意: 在一个multiset中要求支持3种操作: 1.增加一个数 2.删去一个数 3.给出一个01序列,问multiset中有多少这样的数,把它的十进制表示中的奇数改成1,偶数改成0后和给 ...

  9. Codeforces Round #268 (Div. 2) ABCD

    CF469 Codeforces Round #268 (Div. 2) http://codeforces.com/contest/469 开学了,时间少,水题就不写题解了,不水的题也不写这么详细了 ...

  10. 贪心+模拟 Codeforces Round #288 (Div. 2) C. Anya and Ghosts

    题目传送门 /* 贪心 + 模拟:首先,如果蜡烛的燃烧时间小于最少需要点燃的蜡烛数一定是-1(蜡烛是1秒点一支), num[g[i]]记录每个鬼访问时已点燃的蜡烛数,若不够,tmp为还需要的蜡烛数, ...

随机推荐

  1. SV OOP-2

    静态变量 继承性(Inheritance) 抽象类和虚方法virtual methods 多态(Ploymorphism) 通过基类的变量可以使用子类的对象 基类中定义的virtual functio ...

  2. 【BUS】LIN Bus

    概述 随着汽车内电子设备的增多,市场上对于成本低于 CAN 的总线的需求日益强烈,不同的车厂相继开发各自的串行通信(UART/SCI)协议,以在低速和对性能要求不高的场合取代CAN.由于不同车厂定义的 ...

  3. 【canvas】 绘制七巧板

    效果图: 代码 : <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  4. IDE-常用插件

    2021-8-25_IDE-常用插件 1. 背景 提升编写代码的舒适度,提升开发效率 2. 常用插件列表 IDE EVal Reset 白嫖付费的golang编辑器,reset插件可以重置golang ...

  5. [转帖]【SOP】最佳实践之 TiDB 业务写变慢分析

    https://zhuanlan.zhihu.com/p/647831844 前言 在日常业务使用或运维管理 TiDB 的过程中,每个开发人员或数据库管理员都或多或少遇到过 SQL 变慢的问题.这类问 ...

  6. [转帖]SpringBoot项目banner.txt生成教程

    文章目录 近期在做毕业设计,后端框架用到了SpringBoot,可以自己个性化设置banner.txt 地址:https://www.bootschool.net/ascii 可以直接下载,然后直接将 ...

  7. [转帖]深度解读:传奇的Alpha处理器

    https://jishuin.proginn.com/p/763bfbd2cf85 来源:科技新报(台) 长期关心处理器技术发展者,这20年来,很难不每隔一段时间就会偶尔听到「这技术受Alpha影响 ...

  8. 使用TFS CI 又想保留服务运行状态的简单方法

    最近公司使用TFS-CI的方式定期部署测试环境, 但是发现TFS-CI 运行完之后会清理agent所在的测试环境. 运行的进程都会被killed 1. 第一种方法: 本来第一反应 是使用systemd ...

  9. vue3.2新增指令v-memo的使用

    v-memo的讲解 vue3.2中新增了一个性能优化的指令: 这个指令就是v-memo; v-memo:可以做性能优化,v-memo中值若不发生变化,整个子树的更新会被跳过. <div v-me ...

  10. echarts饼状图自定义legend的样式付费

    先看效果图 代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> < ...