9 ABC408 D~F 题解

news/2025/10/10 21:13:23/文章来源:https://www.cnblogs.com/michaele/p/19133895

ABC408 D~F 题解

D

题面

给定一个长度为 \(n\) 的由 01 组成的字符串 \(S\),每次操作可以将某个 0 改成 1,或者将某个 1 改成 0 。

求字符串中至多有一个连续 1 串的最小操作次数。

题解

解法1

考场思路,将每个连续 1 串挑出来,考虑每个 1 串选或者不选。

\(f(i,0/1)\) 表示第 \(i\) 个 1 串选/不选的最小操作次数,分别考虑如何转移。

如果不选,那么不需要将两个连续 1 串中间的 0 变为 1,所以新增操作次数即为当前 1 串的长度。

如果选,那么要和前面最后一个 1 串连起来,或者自己成为第一个 1 串。

有转移:

\[\begin{align*} &f(i, 0) = \min \{ f(i - 1, 0), f(i - 1, 1) \} + len_i \\ &f(i, 1) = \min \{ \min_{1 \le j < i} \{ f(j, 1) - t_j\} + h_i - 1 , sum_{i - 1}\} \end{align*} \]

其中 \(h,t\) 表示一个 1 串的头、尾坐标,\(sum_i\) 表示前 \(i\) 个 1 串的长度和。

解法2

\(sum_i\) 表示前 \(i\) 个位置中 1 的个数。

假设我们枚举了最后 1 串的左右端点 \(l,r\) ,那么答案应该怎么算?

不难得出为 \(2sum_{l - 1} - l + r- 2sum_r + sum_n + 1\)

\(a_i = 2sum_{i - 1} - i, b_i = i - 2sum_i + sum_n + 1\),那么刚才的答案也就能够写成 \(a_l + b_r\)

假设我们固定了一个右端点,我们也就是要找到 \(a_l\) 最小的 \(l\) ,从而用 \(a_l + b_r\) 来更新答案。

我们完全可以用一个变量来维护最小 \(a_l\) ,然后右端点不断向右扫。

code

解法1

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>using namespace std;namespace michaele {const int N = 2e5 + 10;int n, cnt;int f[N][2], sum[N], st[N], top;char s[N];struct seg {int h, t, len;} a[N];void solve () {cnt = 0;cin >> n;scanf ("%s", s + 1);int p = 1;while (p <= n) {if (s[p] == '0') {p ++;continue;}int h = p;while (s[p] == '1' && p <= n) p ++;a[ ++ cnt] = {h, p - 1, p - h};sum[cnt] = sum[cnt - 1] + p - h;}if (cnt == 0) {cout << 0 << endl;return;}memset (f, 0x3f, sizeof f);f[1][0] = a[1].len;f[1][1] = 0;st[1] = 1, top = 1;for (int i = 2; i <= cnt; i ++) {f[i][0] = min (f[i - 1][0], f[i - 1][1]) + a[i].len;int j = st[top];f[i][1] = min (f[j][1] + a[i].h - a[j].t - 1, sum[i - 1]);while (top && f[i][1] - a[i].t <= f[st[top]][1] - a[st[top]].t) top --;st[ ++ top] = i;}cout << min (f[cnt][0], f[cnt][1]) << endl;}void Main () {int T;cin >> T;while (T --) {solve ();}}
}int main () {// freopen ("test/test.in", "r", stdin);// freopen ("test/test.out", "w", stdout);michaele :: Main ();return 0;
}

解法2

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <deque>using namespace std;namespace michaele {const int N = 2e5 + 10, M = N << 1;int n, sum[N], a[N], b[N];char s[N];void solve () {cin >> n;scanf ("%s", s + 1);for (int i = 1; i <= n; i ++) {sum[i] = sum[i - 1] + (s[i] == '1');}if (sum[n] == 0) {cout << 0 << endl;return;}for (int i = 1; i <= n; i ++) {a[i] = 2 * sum[i - 1] - i;b[i] = i - 2 * sum[i] + 1 + sum[n];}int ans = 2e9, mn = 2e9;for (int i = 1; i <= n; i ++) {mn = min (mn, a[i]);ans = min (ans, mn + b[i]);}cout << ans << endl;}void Main () {int T;cin >> T;while (T --) {solve ();}}
}int main () {michaele :: Main ();return 0;
}

E

题面

给定一张 \(n\) 个点,\(m\) 条边的无向连通图,每条边有边权 \(w_i\)

定义某条路径的长度为路径上的边权的异或和,求从 1 到 n 的最短路径长度。

\(2 \le n \le 2 \times 10^5, n - 1 \le m \le 2 \times 10^5\)

\(0 \le w_i \le 2^{30}\)

题解

这种位运算的题,一般来说都要将每一位分开考虑。

这里我们是要求一个从 1 到 n 的最短或路径,我们从高到低考虑每一位。

如果这一位能选 0,那么一定选 0,否则只能选 1。

如何判断这一位能不能选 0 ?

我们可以将边权变为这一位的值,然后跑个 01BFS,看最后 \(dis_n\) 是否为 0 即可。如果这一位能选 0 ,那么要将所有这一位为 1 的边删除,保证后面的选择是在这一位为 0 的前提下的。

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

code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <deque>using namespace std;namespace michaele {const int N = 2e5 + 10, M = N << 1;int n, m;int h[N], ver[M], ne[M], e[M], tot;bool del[M];void add (int x, int y, int z) {ver[ ++ tot] = y;ne[tot] = h[x];h[x] = tot;e[tot] = z;}int dis[N];void bfs (int bit) {memset (dis, 0x3f, sizeof dis);deque <int> q;dis[1] = 0;q.push_front (1);while (q.size ()) {int x = q.front ();q.pop_front ();for (int i = h[x]; i; i = ne[i]) {if (del[i]) continue;int y = ver[i], z = (e[i] >> bit) & 1;if (dis[y] > (dis[x] | z)) {dis[y] = (dis[x] | z);if (z == 0) q.push_front (y);else q.push_back (y);}}}}void solve () {cin >> n >> m;for (int i = 1; i <= m; i ++) {int x, y, z;cin >> x >> y >> z;add (x, y, z);add (y, x, z);}int ans = 0;for (int i = 30; i >= 0; i --) {bfs (i);if (dis[n] != 0) ans += (1 << i);else {for (int j = 1; j <= tot; j ++) {if ((e[j] >> i) & 1) {del[j] = 1;}}}}cout << ans << endl;}
}int main () {michaele :: solve ();return 0;
}

F

题面

\(n\) 个木桩,第 \(i\) 个木桩的高度为 \(H_i\)

小乐要做个游戏。他将任意选一个木桩为起点,然后不断移动到下一个木桩,从木桩 \(i\) 可以移动到木桩 \(j\) 当且仅当 \(H_j \le H_i - D \and|i - j| \le R\)

求他在游戏中最多可以移动多少次。

\(1 \le D, R \le n \le 5 \times 10^5\)

\(H\)\(1 \sim n\) 的排列

题解

这道题转移有两个限制,应该算个 trick。

如果单个限制,很好做,第一个维护一个 \(set\),第二个维护线段树。

但这两个合到一起,我们可以从小到大枚举 \(H_i\),然后将 \(H_i - D\) 对应位置的 \(f\) 单点修改到线段树中,然后每次在线段树上查询对应区间的最大值更新 \(H_i\) 对应位置的 \(f\) 即可。

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

code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <deque>using namespace std;namespace michaele {#define ls (p << 1)#define rs (p << 1 | 1)const int N = 5e5 + 10, M = N << 1;int n, D, R;int a[N], id[N], f[N];int val[N << 2];void update (int p) {val[p] = max (val[ls], val[rs]);}void modify (int p, int l, int r, int pos, int d) {if (l == r) {val[p] = d;return;}int mid = (l + r) >> 1;if (pos <= mid) modify (ls, l, mid, pos, d);else modify (rs, mid + 1, r, pos, d);update (p);}int query (int p, int l, int r, int x, int y) {if (x <= l && r <= y) {return val[p];}int mid = (l + r) >> 1;int res = -1;if (x <= mid) res = max (res, query (ls, l, mid, x, y));if (mid < y) res = max (res, query (rs, mid + 1, r, x, y));return res; }void solve () {cin >> n >> D >> R;for (int i = 1; i <= n; i ++) {cin >> a[i];id[a[i]] = i;}memset (val, -1, sizeof val);int ans = 0;for (int i = 1; i <= n; i ++) {int pos = id[i];if (i > D) {modify (1, 1, n, id[i - D], f[id[i - D]]);int tmp = query (1, 1, n, pos - R, pos + R); if (tmp == -1) f[pos] = 0;else f[pos] = tmp + 1;} else {f[pos] = 0;}ans = max (ans, f[pos]);}cout << ans << endl;}
}int main () {michaele :: solve ();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/934410.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

8 ABC425 G 题解

ABC425 G 题面 给定两个正整数 \(N,M\) 以及一个长度为 \(N\) 的非负整数序列 \(A = A_1, A_2, ..., A_N\)。求 \[\sum_{x = 0}^{M - 1} \min_{1 \le i \le N} (x \oplus A_i) \]\(1 \le N \le 2 \times 10^5\) \(1 \l…

智能防御,安全赋能:AI-FOCUS 滤海AI DLP 化解外部 AI 风险

在“员工把数据投喂给第三方AI”的常见场景下,企业需要一款可在输入与上传瞬时介入的产品。AI-FOCUS 滤海AI DLP 以流式网关为核心,在用户向大模型输入文本与提交文件/图片时进行敏感数据识别,按风险等级执行放行、…

VS code 中代码补全 自动补全函数括号

使用vscode的pylance插件补全python代码的时候无法补全函数的括号 需要在settings.json中添加这一行即可

学习ReAct并使用langgraph实现一个简单的ReAct AI Agent!!

ReAct介绍 要介绍ReAct最好要知道它是从哪来的。 ReAct这个概念出自《REACT : SYNERGIZING REASONING AND ACTING IN LANGUAGE MODELS》这篇很牛的论文。 论文地址:https://arxiv.org/abs/2210.03629 我们先来看下这篇…

23种设计模式之【策略模式】-核心原理与 Java 实践 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

abc 408 d~f

这次做了一次 abc,d 做出来了,但是比较麻烦,又用正确方法写了一遍,整理一下 d,e,f,g 有一些超纲。 abc408d 考虑把区间 \(l,r\) 最后变成 1,然后尝试去表示这个时候的答案。 \(sum[i]\) 表示 \(i\) 位置以及之前…

RMQ与LCA学习笔记

在开始之前先提一下RMQ与LCA这两个东西有什么关系 对于一个序列,对它构建出一颗笛卡尔树之后,两个点的LCA就是原序列中这两个点之间的最大值/最小值(取决于建树时的比较方式) 而对于一棵树,求出来他的欧拉序之后,…

the charm of Chinese language

The charm of Chinese language is you use it to read books. when I can read the original books translation as Chinese. I found the original one lets people dizzy, maybe it needs some graphs to make the …

mamba-硬件感知算法

扫描操作由于A B C这些矩阵现在是动态的了,因此无法使用卷积表示来计算它们(卷积核是固定的),因此,我们只能使用循环表示,如此也就而失去了卷积提供的并行训练能力 Mamba通过并行扫描(parallel scan)算法使得最终并…

完整教程:lua代码解析1

完整教程:lua代码解析1pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", &qu…

system表空间丢失部分文件恢复---惜分飞

system表空间丢失部分文件恢复---惜分飞联系:手机/微信(+86 17813235971) QQ(107644445) 标题:system表空间丢失部分文件恢复 作者:惜分飞©版权所有[未经本人同意,不得以任何形式转载,否则有进一步追究法律责任…

二维数点

介绍 给出一个二维平面內的若干个点,多次询问某个矩形区域內包含多少个点(边界也算)。又或者,给一个长为 n nn 的序列,多次询问区间 [ l , r ] [l,r][l,r] 中值在 [ x , y ] [x,y][x,y] 内的元素个数。 例题 P190…

gitee和github如何修改仓库名并且保持与原远程仓库的连接?(手把手教学) - 实践

gitee和github如何修改仓库名并且保持与原远程仓库的连接?(手把手教学) - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font…

2025.10.10总结 - A

今天上了节英语,感觉还可以,下雨了,一直在宿舍,感觉很爽。

[20251010]建立完善tpt的prr.sql脚本.txt

[20251010]建立完善tpt的prr.sql脚本.txt--//昨天在测试时不小心输入pr命令时多输入一个r,没想到居然执行了,说明在本目录或者SQLPATH环境目录下存在prr.sql脚本。--//当时忙着处理其他事情,先把这件事情放一放,今…

第十一篇

今天是10月10号,今天只上了一节英语课,学习了新的单词,颇有收获。

[Flutter] Flutter APK构建签名并推广到Github workflow

[Flutter] Flutter APK构建签名并推广到Github workflowFlutter APK构建签名并推广到Github workflow 最近在开发flutter软件的时候发现构建出来的apk在手机上不能直接覆盖更新,会提示签名不一致,但由于我的软件是在…

Windows 电脑安装 XTerminal 1.25.1 x64 版(带安装包下载关键词)​

Windows 电脑安装 XTerminal 1.25.1 x64 版(带安装包下载关键词)​​XTerminal​ 是一款运行在 Windows 系统上的终端工具(类似命令行窗口),通常用于开发者、运维人员或高级用户来执行命令、连接远程服务器、运行…

YOLOv11的神经辐射场(NeRF)辅助训练-(通过合成视角增强内容多样性)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …