当前位置: 首页 > news >正文

AtCoder Beginner Contest 408

A - Timeout

思路:给定一个单增数组,和一个最大间隔,判断数组是否严格满足间隔不大于最大间隔。这就是个水题,倒是读题理解了一会儿

/*
Author Owen_Q
*/
#include <bits/stdc++.h>using namespace std;int main() {ios_base::sync_with_stdio(false), cin.tie(nullptr);int n, s;cin >> n >> s;int pre = 0;bool awake = true;for (int i = 0; i < n; i++) {int t;cin >> t;if (t - pre > s) { awake = false; }pre = t;}if (awake) { cout << "Yes"; } else { cout << "No"; }return 0;
}

B - Compression

思路:给定一个数组,要求将数组内元素去重并从小到大排序。这个题的题意明显比上一题通俗易懂多了,方案也很简单,直接扔set里即可

/*
Author Owen_Q
*/
#include <bits/stdc++.h>using namespace std;int main() {ios_base::sync_with_stdio(false), cin.tie(nullptr);set<int> sets;int n;cin >> n;for (int i = 0; i < n; i++) {int a;cin >> a;sets.insert(a);}cout << sets.size() << endl;for (auto i: sets) {cout << i << " ";}cout << endl;return 0;
}

C - Not All Covered

思路:有n个线段覆盖二维区域,求最短被覆盖最少的点所覆盖的层数。这个看起来像是区间求和,想到树状数组。但在想想这只是个c题,应该不会这么难,于是想到,利用差分数组,通过维护区间的两头来构造最终的线段。这个思路还是挺经典的

/*
Author Owen_Q
*/
#include <bits/stdc++.h>using namespace std;const int MAXM = 1e6 + 5;int guard[MAXM];int main() {ios_base::sync_with_stdio(false), cin.tie(nullptr);int n, m;cin >> n >> m;memset(guard, 0, sizeof guard);for (int i = 0; i < m; i++) {int l, r;cin >> l >> r;guard[l]++;guard[r + 1]--;}int minGuard = m;for (int i = 1; i <= n; i++) {guard[i] += guard[i - 1];// cout << guard[i] << " ";minGuard = min(minGuard, guard[i]);}cout << minGuard << endl;return 0;
}

D - Flip to Gather

思路:给定一个01字符串,每次操作可以将子串中的一位01互换,求最少得操作次数使得串中所有的1连续。

首先想到dp,按位dp,分全0,先0后1,先1后0和全1四种状态进行转移。后来发现先0后1和先1后0两种状态由于根本无法知道0和1的数量,因此无法进行转移,而宣告破产。之后又想到先将字符串变为全0或者全1,然后从边开始加数,但此时重新审题突然发现,其实先0后1最后0这种方案也是满足条件的。最终决定还是重回dp重新思考。

重新整理,其实有分全0(0),先0后1(01),先1后0(10),全1(1)和先0后1最后0(010)这五种方案。由于向后递归,因此过程中其实我们不用关注前缀0的数量,于是,全1和先0后1可以合并为包含部分0且1结尾([0]1),先1后0和先0后1最后0可合并为包含部分0后特定1加特定0([0]10)。那么转移方程就简单了。全0直接由自己加1转移来,部分0且1结尾可以由自己或者全0加1得来。部分0后特定1加特定0则可以由自己或者上述两种方案加0转移来

场景标识转移前当前位为1当前位为0
全00dp[0]dp[0]+1dp[0]
部分0且1结尾[0]1dp[1]min(dp[0],dp[1])min(dp[0],dp[1])+1
部分0后特定1加特定0[0]10dp[2]min(dp[0],dp[1],dp[2])+1min(dp[0],dp[1],dp[2])
/*
Author Owen_Q
*/
#include <bits/stdc++.h>using namespace std;const int MAXM = 2e5 + 5;int main() {ios_base::sync_with_stdio(false), cin.tie(nullptr);int t;cin >> t;while (t--) {int n;cin >> n;string s;cin >> s;int dp[6];if (n <= 2) {cout << 0 << endl;} else {if (s[0] == '0' && s[1] == '0') {dp[0] = 0;dp[1] = 1;dp[2] = 0;} else if (s[0] == '0' && s[1] == '1') {dp[0] = 1;dp[1] = 0;dp[2] = 1;} else if (s[0] == '1' && s[1] == '0') {dp[0] = 1;dp[1] = 1;dp[2] = 0;} else if (s[0] == '1' && s[1] == '1') {dp[0] = 2;dp[1] = 0;dp[2] = 1;}for (int i = 2; i < n; i++) {if (s[i] == '1') {dp[3] = dp[0] + 1;dp[4] = min(dp[0], dp[1]);dp[5] = min(dp[2], dp[4]) + 1;} else {dp[3] = dp[0];dp[4] = min(dp[0] + 1, dp[1] + 1);dp[5] = min(dp[2], dp[4] - 1);}dp[0] = dp[3];dp[1] = dp[4];dp[2] = dp[5];}int re = min(min(dp[0], dp[1]), dp[2]);cout << re << endl;}// int num0 = 0;// int num1 = 0;// for (int i = 0; i < n; i++) {//     if (s[i] == '0') {//         num0++;//     } else {//         num1++;//     }// }// int re = min(num0, num1);// int current = num0;// for (int i = 0; i < n; i++) {//     if (s[i] == '1') {//         current++;//     } else {//         current--;//     }//     re = min(re, current);// }// current = num1;// for (int i = 0; i < n; i++) {//     if (s[i] == '1') {//         current--;//     } else {//         current++;//     }//     re = min(re, current);// }// cout << re << endl;}return 0;
}

此外,看了一下大佬们的做法,其实大部分大佬用的都是和我一样的方案,但又发现了另一种很巧妙的方案,即用前缀合暴力枚举不同1的开始位置所需进行的最少操作次数。首先,预处理 pre[k] 数组,表示前 k 位包含多少个0。假设区间 [i,j] 之间的数均为1,那么其实就是需要求第一段0,第二段1和第三段0分别需要操作多少次。

第一段0需要操作次数:i-pre[i-1]

第二段1需要操作次数:pre[j]-pre[i-1]

第三段0需要操作的次数:n-1-j +i- pre[n-1] + 2pre[j]-2pre[i-1]

求和即为 2pre[j]-j + i - 2pre[i-1] +n-1-pre[n-1]

要求上式的最小值,分解一下f(x) = 2pre[x]-x, t= i - 2pre[i-1] +n-1-pre[n-1]

那么原式就等于了 f(x)+t, 于是,从后往前遍历求解即可

首先初始化,假设 i=j=n-1, 原式即变成了 pre[n-1]- 2pre[n-2] +n-1

f(n-1)=2pre[n-1]-n+1

/*
Author Owen_Q
*/
#include <bits/stdc++.h>using namespace std;const int MAXN = 2e5 + 5;
int pre[MAXN];int getPre(int x) {if (x >= 0) {return pre[x];}return 0;
}int main() {ios_base::sync_with_stdio(false), cin.tie(nullptr);int t;cin >> t;while (t--) {int n;cin >> n;string s;cin >> s;memset(pre, 0, sizeof pre);pre[0] = s[0] == '0' ? 1 : 0;for (int i = 1; i < n; i++) {pre[i] = pre[i - 1];if (s[i] == '0') {pre[i]++;}}int re = min(n - getPre(n - 1), getPre(n - 1) - 2 * getPre(n - 2) + n - 1);// cout << re << "*";int currentF = 2 * getPre(n - 1) - n + 1;for (int i = n - 2; i >= 0; i--) {int t = i - 2 * getPre(i - 1) + n - 1 - getPre(n - 1);currentF = min(currentF, 2 * getPre(i) - i);re = min(re, currentF + t);}cout << re << endl;}return 0;
}

E - Minimum OR Path 

思路:求图中1点到n点的最小路径或和。一开始想利用异或的各种性质之类的,但是最终无功而返,最典型的就是两个大数的或和可能比一个大数和一个小数的或和要小。不过倒是有个性质可以用,就是两个数的或和一定不小于其中任意一个数。于是考虑按位运算,从高位往低位进行枚举,找到所有能使当前位保持0的边,然后看一下能否使得1点和n点连通,如果不能,则当前位一定为1,不可避免。否则,当前位可以保持0

/*
Author Owen_Q
*/
#include <bits/stdc++.h>using namespace std;const int MAXN = 2e5 + 5;
int u[MAXN], v[MAXN], w[MAXN], pre[MAXN];int findPre(int x) {return x == pre[x] ? x : pre[x] = findPre(pre[x]);
}void unionUV(int u, int v) {int preU = findPre(u);int preV = findPre(v);if (preU != preV) {pre[preU] = preV;}
}bool check(int k, int n, int m) {for (int i = 1; i <= n; i++) {pre[i] = i;}for (int i = 0; i < m; i++) {if ((w[i] | k) == k) {unionUV(u[i], v[i]);}}// cout << k << " " << findPre(1) << " " << findPre(n) << endl;return findPre(1) == findPre(n);
}int main() {ios_base::sync_with_stdio(false), cin.tie(nullptr);int n, m;cin >> n >> m;for (int i = 0; i < m; i++) {cin >> u[i] >> v[i] >> w[i];}int re = 0;for (int i = 29; i >= 0; i--) {if (!check(re | (1 << i) - 1, n, m)) {re |= 1 << i;}}cout << re << endl;return 0;
}

http://www.xdnf.cn/news/970273.html

相关文章:

  • 电路笔记(元器件):并串转换芯片 SN65LV1023A 10:1 LVDS 串行器/解串器变送器 100 至 660Mbps
  • HarmonyOS开发:设备管理使用详解
  • shell脚本总结15:grep命令的使用方法
  • 不变性(Immutability)模式
  • 丝路幽径:穿梭于Linux多线程控制的秘境
  • 专题一_双指针_快乐数
  • LeetCode 3442.奇偶频次间的最大差值 I:计数
  • 使用分级同态加密防御梯度泄漏
  • Web 毕设篇-适合小白、初级入门练手的 Spring Boot Web 毕业设计项目:智驿AI系统(前后端源码 + 数据库 sql 脚本)
  • 实现多路视频截图预览之后上传到后台系统
  • 2025年ASOC SCI2区TOP,协同搜索框架自适应算法+多无人机巡检规划,深度解析+性能实测
  • 专题一_双指针_复写零
  • HDFS 3.4.1 集成Kerberos 实现账户认证
  • 驭码CodeRider 2.0深度测评:助力高效开发【探索化学奇妙世界】网站
  • 【靶场】xxe漏洞2
  • 黑马Mybatis
  • UE5 学习系列(三)创建和移动物体
  • MySQL事务——博主总结
  • C# Serilog 日志
  • 西电计组第四章-存储系统
  • 72道Nginx高频题整理(附答案背诵版)
  • 【Qt】显示类控件 QLabel、QLCDNumer、QProgressBar、QCalendarWidget
  • ROS-编写工作区、功能包、节点
  • 通过Elastic EDR看smbexec并进行二次开发Bypass
  • @component、@bean、@Configuration的区别
  • 在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
  • MySQL:InnoDB架构(内存架构篇)
  • Grey任命李文杰为中国总裁,开启增长新章
  • 云服务运行安全创新标杆:阿里云飞天洛神云网络子系统“齐天”再次斩获奖项
  • 12要素法:构建高效云原生应用