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

题解:AT_apc001_h Generalized Insertion Sort

为数不多能瞎搓出来的构造。

题意:给出一棵以 \(0\) 为根的树和每个点上的值 \(a_i\),每次可以对一个点 \(u\) 进行以下操作:

  • 设从根往下走到 \(u\) 的路径为 \(p_1,p_2,\cdots p_k\),那么令 \(a_{p_i}\leftarrow a_{p_{i+1}}\),这里特殊令 \(p_{k+1}=p_1\)

需要在不多于 \(25000\) 次操作内使得 \(a_i=i\)\(n\le 2000\)

做法:

考虑这个操作在干啥,我们其实可以主要认为这个操作可以帮我们把根节点的数塞到任意一个位置,这样思考会方便一点。

首先考虑特殊情况链怎么做。一个想法是我们维护一个目前已经取出来的元素的序列,我们只需要保持这个序列的相对顺序和链的顺序一样,那么一步步还原就可以得到整个链。同时,这个序列在链上置于最末端,要不然需要还原更大的时候就会往前推一下就爆炸了。

那么考虑将 \(a_0\) 去进行还原,假设我们已经还原的部分值是 \(b_1,b_2\cdots b_k\),我们只先需要找到第一个小于 \(a_0\) 的位置,在这个位置做一次我们的操作,就可以成功构造出新的有序序列。并且这个东西是在链的末尾,所以非常好定位 \(a_0\) 的位置。

但是这个题是对任意的树做,我们需要拓展。一个很基础的想法是,因为叶子在最末端,所以我们肯定需要先还原他们。再贪心一点,我们没有必要只还原叶子,我们完全可以把这个叶子向上的一条没有分叉的链,或者说把叶子的虚树建出来之后到父亲这一部分的链一起处理。先不考虑操作次数的问题,我们先来把算法具体流程做完。

首先先把这些链按叶子编号分类。然后同样考虑我现在有一个 \(a_0\) 该如何插入。如果 \(a_0\) 在我这一轮分的链内,那么就按照对链的操作同样处理,只不过是同时处理多条链罢了;而如果不是,那我们就需要用这个数把别的数都挤上来,那就选一个深度最深的我目前还没确定的点。注意,这里确定的意思为,在前面的轮次中被还原,或者在当前轮次中已经有当前链的元素占据了这个位置。但是这样,如果我存在一条链都不是当前轮次确定的点一直操作就爆炸了,所以我们还需要要求这个点不能被操作过了。因为我们并不在乎那些这一轮不被确定的点具体的编号,所以操作两次同一个点,和操作一次这一个点和他的父亲本质是相同的,所以多次操作是没有意义的。这样做是一个 bfs 序的逆序,所以一定也是能把所有的数都挤上去一次的。

考虑复杂度,首先对于一轮来说,我链上的每个点操作次数是链长的,而其他的点都操作一次,操作次数为 \(O(n)\)。而同时,考虑怎么样尽量构造轮数更多,假设一个点的子树分别需要 \(x_1,x_2,\cdots x_n\) 轮去解决,那么会发现,当只有一个最大值的时候,我显然也只需要这么多轮;当我有两个最大值的时候,我需要的轮数是最大值加一,所以最差的情况也就是一个满二叉树的情况,轮数是 \(O(\log n)\) 的,总共操作次数是 \(O(n\log n)\) 的,可以通过此题。

因为我写的时候思路有点混乱,导致代码可读性可能不是很高/kel。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2005;
int n, vis[maxn], a[maxn], id[maxn], dep[maxn], use[maxn], f[maxn], cnt, ut[maxn];
vector<int> v[maxn], pos, e[maxn], nw[maxn];
int dfs(int u) {if(vis[u])return 0;int son = 0, p = 0, f = 0;for (int i = 0; i < e[u].size(); i++) {int v = e[u][i];dep[v] = dep[u] + 1;int t = dfs(v);if(t != 0)p = t, son++;f |= t == -1;}	if(f)return -1;if(son <= 1)vis[u] = cnt;elsereturn -1;if(son == 0)p = u, pos.push_back(p);v[p].push_back(u), id[u] = p;return p;
}
vector<int> v1;
void shift(int x) {v1.push_back(x);int v = a[0];vector<int> nw;for (int p = x; p; p = f[p])nw.push_back(p);nw.push_back(0);for (int i = nw.size() - 1; i > 0; i--)a[nw[i]] = a[nw[i - 1]];a[x] = v;
}
int main() {cin >> n;for (int i = 1; i < n; i++) {cin >> f[i];e[f[i]].push_back(i);}for (int i = 0; i < n; i++)cin >> a[i];while(!vis[0]) {cnt++;pos.clear();dfs(0);for (int i = 0; i < n; i++)use[i] = 0, ut[i] = 0;while(!use[a[0]]) {//	cout << "adf" << endl;if(vis[a[0]]) {int p = 0;for (int j = 0; j < nw[id[a[0]]].size(); j++) {int t = nw[id[a[0]]].size() - 1 - j;if(dep[nw[id[a[0]]][j]] < dep[a[0]])p = j + 1;}int t = nw[id[a[0]]].size() - p;use[a[0]] = 1;nw[id[a[0]]].insert(p + nw[id[a[0]]].begin(), a[0]);shift(v[id[a[0]]][t]);}else {int p = -1;for (int i = 1; i < n; i++) if(((vis[i] == cnt || vis[i] == 0) && !use[a[i]] && (p == -1 || p < i) && !ut[i]))p = i;//	cout << a[0] << endl;if(p != -1) {ut[p] = 1;shift(p);}elsebreak;}
//				for (int i = 0; i < n; i++)
//					cout << a[i] << " ";
//				cout << endl;}
//		for (int i = 0; i < n; i++)
//			cout << vis[i] << " ";
//		cout << endl;}if(v1.size() > 25000)exit(100);cout << v1.size() << endl;for (int i = 0; i < v1.size(); i++)cout << v1[i] << endl;
//	for (int i = 0; i < n; i++)
//		cout << a[i] << " ";return 0;
}
/*
10
0 1 0 3 2 4 5 6 8
9 8 7 6 5 4 3 2 1 0
*/
http://www.hskmm.com/?act=detail&tid=39107

相关文章:

  • 记一次thinkphp3.2项目迁移失败的原因。 is currently unable to handle this request. HTTP ERROR 500
  • 20232310 2025-2026-1 《网络与系统攻防技术》实验三实验报告
  • [SWPUCTF 2024 秋季新生赛]http标头 WP
  • 20251025 之所思 - 人生如梦
  • Jerrum–Sinclair 全有或全无定理
  • 一种解决所有 OI 问题的算法:Dream 算法
  • CobaltStrike流量分析
  • 【论文阅读】ASPS: Augmented Segment Anything Model for Polyp Segmentation - 指南
  • RuoYi-Cloud 认证实现
  • 初步学习计算机相关知识有感 - fang
  • 2025年自动上料机厂家权威推荐榜:螺旋上料机/真空上料机/粉末上料机,高效输送系统精准选型指南
  • 用代码将txt分别转换成列表和字典
  • 每日反思(2025_10_25)
  • AtCoder Beginner Contest 429 ABCDEF 题目解析
  • 2025年提升机厂家推荐排行榜,自动提升机,垂直提升机,物料提升机,工业提升设备公司精选
  • 刷题日记—数组—布尔数组的应用
  • 详细介绍:k8s中的kubelet
  • 树状数组 区间加 区间和 小记
  • 实验二 现代C++编程初体验
  • 昨夜雨疏风骤
  • 明天的任务
  • Windows SMB权限提升漏洞遭活跃利用
  • 江西振兴杯决赛Misc全解
  • 完整教程:Webpack5 第四节
  • 2025.10.25总结
  • ABC429
  • 10.25 CSP-S模拟39/2025多校冲刺CSP模拟赛8 改题记录
  • ABC429(C,D,E)
  • 玩转单片机之智能车小露——数字与字符串的转换与打印
  • 数据采集作业1 102302111 海米沙