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

题解:AtCoder ARC209D A_A_i

闲话

帅炸了。

这是主播被 \(n=1\) 的 case 卡爆了,望周知。

题意

给定长度为 \(n\) 的序列 \(a\),值域为 \([1,n]\),有一些位置未确定。你需要给这些未确定的位置的确定取值,使得序列 \(b_i=a_{a_i}\) 的字典序最小。多测,\(1\leq T\leq 10^5\)\(1\leq n\leq\sum{n}\leq 5\times 10^5\)

题解

首先特判掉一些 corner case。

\(a_1=-1\lor a_1=1\),我们让所有 \(-1\) 的位置都填 \(1\) 显然最优。

\(a\) 中恰好有 \(1\)\(-1\) 位于 \(pos\) 处,考虑若存在 \(i\) 使得 \(a_i>i\land a_i=pos\),我们就令 \(a_{pos}\gets 1\);否则我们令 \(a_{pos}\) 为最靠前的全局最小值的位置(注意这里求全局最小值时要先令 \(a_{pos}\gets pos\))。这是因为,如果存在 \(i\) 使得 \(a_i>i\land a_i=pos\),那么 \(b_i\) 要比 \(b_{pos}\) 更靠前,所以我们肯定优先把 \(b_i\) 置为 \(1\);否则我们就要让 \(b_{pos}\) 尽可能小,在此基础上,考虑到后面的一些满足 \(a_i=pos\) 的位置,我们还要令 \(a_{pos}\) 尽可能小,于是 \(pos\) 自然就取最靠前的全局最小值的位置了。

接下来考虑 \(a\) 中至少有 \(2\)\(-1\) 的情况。

首先和前面一种 case 类似,若存在 \(i\) 使得 \(a_i>i\land a_{a_i}=-1\),则令 \(a_{a_i}\gets 1\)

然后考虑所有 \(a_i=-1\) 的位置,不妨找出 \(a\) 中第一个 \(1\) 的位置 \(p\)\(\forall a_i=-1,a_i\gets p\)。若不存在 \(a_i=1\),则令 \(p\) 为最后一个 \(a_i=-1\) 的位置,强制令 \(a_p\gets 1\)。这样子除了最后一个位置,每个 \(-1\) 对应的 \(b\) 都能取到 \(1\),比较优秀。

但是可以发现,这样没有考虑到那些 \(a_i\neq -1\land a_i<i\land a_{a_i}=-1\)\(i\) 对应的 \(b_i\) 的取值,换句话说,我们还要尽可能最小化 \(a_i\)。怎样可以进一步最小化 \(a_i\) 呢?可以发现,我们只能考虑提前把某个 \(-1\) 的位置置为 \(1\)。考虑最小的 \(i\) 使得 \(a_i\neq -1\land a_i<i\land a_{a_i}=-1\),那么显然 \(i\) 之前的 \(-1\) 不能动,于是考虑 \(i\) 之后第一个 \(j\) 满足 \(a_j=-1\),我们可以尝试把这个 \(a_j\) 置为 \(1\)。具体来说,我们直接令前文中找到的 \(p\) 和这个 \(j\)\(\min\) 即可。

依照上述讨论实现即可。时间复杂度为 \(\mathcal{O}(\sum n)\)

代码
#include <bits/stdc++.h>using namespace std;#define lowbit(x) ((x) & -(x))
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pii;
const int N = 5e5 + 5;template<typename T> inline void chk_min(T &x, T y) { x = min(x, y); }
template<typename T> inline void chk_max(T &x, T y) { x = max(x, y); }int T, n, cnt, a[N];int main() {ios::sync_with_stdio(0), cin.tie(0);cin >> T;while (T--) {cin >> n, cnt = 0;for (int i = 1; i <= n; ++i) cin >> a[i], cnt += a[i] == -1;if (cnt == 1) {int pos = 0, mnp = 0; bool flag = 0;for (int i = n; i; --i) {if (a[i] == -1) pos = i;else {if (a[i] == pos) { flag = 1; break; }if (!mnp || a[i] <= a[mnp]) mnp = i;}}if (!mnp) mnp = pos;if (pos < a[mnp] || (pos == a[mnp] && pos < mnp)) mnp = pos;a[pos] = flag ? 1 : mnp;} else if (a[1] == -1 || a[1] == 1) {for (int i = 1; i <= n; ++i) if (a[i] == -1) a[i] = 1;} else if (cnt) {for (int i = 1; i <= n; ++i) if (a[i] > i && a[a[i]] == -1) a[a[i]] = 1;int pos = 1;for (int i = 1; i <= n; ++i)if (a[i] == 1) { pos = i; break; }else if (a[i] == -1) pos = i;for (int i = 1; i <= n; ++i) if (~a[i] && a[i] < i && a[a[i]] == -1) {int p = i + 1;while (p <= n && ~a[p]) ++p;chk_min(pos, p); break;}for (int i = 1; i <= n; ++i) if (a[i] == -1) a[i] = pos;a[pos] = 1;}for (int i = 1; i <= n; ++i) cout << a[a[i]] << " \n"[i == n];}return 0;
}
http://www.jsqmd.com/news/40564/

相关文章:

  • 代码制作数学动画 python manim jjmpeg - 何苦
  • 重组融合蛋白技术概述
  • OpenEuler安装宝塔
  • 20230827 - Balancer 攻击事件:价格操纵 + 精度丢失的经典组合拳
  • 我的标题2
  • 破解cocos creator 2.3.2, 让它支持M芯片
  • Kotlin Coroutines
  • 我的标题
  • 深入解析:软考中级-系统集成项目管理工程师**的超详细知识点笔记。
  • GeoScene Pro试用申请
  • 题解:P13573 [CCPC 2024 重庆站] Pico Park
  • 【AI智能体】Coze 提取对标账号短视频生成视频文案实战详解 - 指南
  • Java Benchmark使用
  • 实用指南:12-机器学习与大模型开发数学教程-第1章1-4 导数与几何意义
  • 基于Vue社区共享游泳馆预约高效的系统n897q36e (工具+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • docker登录容器镜像仓库
  • 吴恩达深度学习课程二: 改善深层神经网络 第三周:超参数调整,批量标准化和编程框架(一)超参数调整
  • Go-秘籍-全-
  • Kotlin中的flow、stateflow、shareflow之间的区别和各自的功能 - 教程
  • 非离散网络流——P3347 [ZJOI2015] 醉熏熏的幻想乡
  • [note] 素数判定与分解质因数
  • 不能识别adb/usb口记录 - 实践
  • 恭喜自己,挑战成功! - Ghost
  • 如何在测试覆盖不足后补充验证
  • react动态表单
  • 完整教程:PDFBox - PDDocument 与 byte 数组、PDF 加密
  • Dark Side of the Moon
  • flask:自定义异常
  • 图片合集
  • OpenWrt路由的端口映射问题