当前位置: 首页 > 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.rkmt.cn/news/49848.html

相关文章:

  • Kotlin Coroutines
  • 我的标题
  • Java Benchmark使用
  • Go-秘籍-全-
  • Kotlin中的flow、stateflow、shareflow之间的区别和各自的功能 - 教程
  • 非离散网络流——P3347 [ZJOI2015] 醉熏熏的幻想乡
  • Dark Side of the Moon
  • 图片合集
  • 升幂引理(LTE)
  • OpenWrt路由的端口映射问题
  • 解码IPC-管道与信号
  • How-to-extract-text-from-PDF-Image-files-OCR-CarlZeng
  • 升鲜宝供应链管理系统、各端的访问地址及nginx 真实的配置方法
  • 2025.11.14模拟赛
  • uiautomator2元素查看器WEditor的安装和启动
  • MI50 在ubuntu 下 风扇控制实现
  • nvm不能下载安装低版本node解决办法
  • 完整教程:【实时Linux实战系列】实时 Linux 在边缘计算网关中的应用
  • 20251114——读后感5
  • 251114
  • 好题集 (4) - CF487E Tourists
  • Http基础协议和解析 - 指南
  • 2025年问题肌培训企业最新专业推测top5:技术创新与实战效能全面升级,做好皮肤管理,搞定皮肤亚健康、祛痘祛斑。
  • 备份一点有趣的东西(期刊资源)
  • Swift 和 Tesseract OCR 进行验证码识别
  • Python安装uiautomator2
  • 用【WPF+Dlib68】实现 侧脸 眼镜虚拟佩戴 - 用平面图表现空间视觉 - 教程
  • 2025年11月徐州网站开发服务商怎么选
  • 好题集 (3) - LG P2122 还教室
  • python3如何切换路径