1 条题解
-
0
自动搬运
来自洛谷,原作者为

dawnlight327
Thou mayest.搬运于
2025-08-24 23:18:06,当前版本为作者最后更新于2025-06-16 12:58:18,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
整体思路
没啥难度,且时间和空间都很足,可以直接模拟。模拟题分步骤解决。
- 把所有积木用向量排序并且排名。这里 vector 的排序需注意。
sort(val.begin(), val.end());-
统计连续数对。这里可以使用 map 来存储数字与其排序位置的关系,方便便利时调用。
-
计算操作次数。我们可以通过画图找规律以及代值法发现公式。
分裂次数 总积木数 初始塔数 有效连续对数
合并次数 总积木数 有效连续对数
这样就结束了。这里附满分代码,代码中有注解。
#include <bits/stdc++.h> using namespace std; int n; // 塔的数量 map<int, int> rmap; // 数字到其排序位置的映射(用于快速查找数字的顺序) vector<vector<int>> ts; // 存储所有塔的积木数字(按从上到下顺序) vector<int> val; // 存储所有积木上的数字 int main() { cin >> n; for (int i = 0; i < n; i++) { int k; cin >> k; // 读取当前塔的积木数量 vector<int> t(k); // 创建存储当前塔积木的容器 for (int j = 0; j < k; j++) { cin >> t[j]; // 读取当前塔的每个积木数字(从上到下顺序) val.push_back(t[j]); // 将数字存入全局数字列表 } ts.push_back(t); // 将当前塔存入塔列表 } sort(val.begin(), val.end()); // 对所有积木数字进行排序,得到从小到大的顺序 int m = val.size(); // 总积木数量 // 建立数字到其排序位置的映射(排序后第1小的数字映射为1,第2小的映射为2,依此类推) for (int i = 0; i < m; i++) { rmap[val[i]] = i + 1; } int x = 0; // 记录各塔中满足"相邻数字在目标序列中也相邻"的对数 for (int i = 0; i < n; i++) { int k = ts[i].size(); // 当前塔的积木数量 // 检查塔中每对相邻积木 for (int j = 0; j < k - 1; j++) { int a = ts[i][j]; // 当前积木数字(上方) int b = ts[i][j + 1]; // 下方积木数字 int ra = rmap[a]; // 上方积木在目标序列中的位置 int rb = rmap[b]; // 下方积木在目标序列中的位置 // 如果下方积木在目标序列中是上方积木的下一个(即形成连续递增对) if (ra + 1 == rb) { x++; // 记录这对有效连续对 } } } // 计算最少操作次数 // 分裂次数 = 总积木数 - 初始塔数 - 有效连续对数 int s = m - n - x; // 合并次数 = 总积木数 - 1 - 有效连续对数(目标是将所有积木合并成1塔,需要m-1次合并,但连续对可减少合并次数) int c = m - 1 - x; cout << s << " " << c << endl; return 0; }
- 1
信息
- ID
- 12521
- 时间
- 3000ms
- 内存
- 1024MiB
- 难度
- (无)
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者