1 条题解
-
0
算法思路
本题通过巧妙的区间查询来推断排列的相对顺序,核心思想是利用相邻区间的关系确定单调性。
关键观察
-
基础差值:b[i] = query(i-1, i) 得到相邻元素的绝对差值
-
三角关系:c[i] = query(i-1, i+1) 帮助判断中间元素的相对位置
-
单调性判断:通过比较 c[i-1] 与 b[i] + b[i-1] 的关系确定方向
代码实现
#include <bits/stdc++.h> #include "xylophone.h" using namespace std; const int $N = 5e3 + 5$, inf = 1e9; int a[$N$], n, b[$N$], c[$N$], ff[$N$]; void solve(int n1) { n = n1; // 步骤1:获取相邻元素的绝对差值 for (int i = 2; i <= n; i++) b[i] = query(i - 1, i); // 步骤2:获取三个连续元素的关系 for (int i = 2; i < n; i++) c[i] = query(i - 1, i + 1); // 步骤3:确定单调性方向 ff[2] = 1; // 初始方向设为递增 for (int i = 3; i <= n; i++) { if (c[i - 1] == b[i] + b[i - 1]) ff[i] = 1; // 保持同向 else ff[i] = -1; // 改变方向 } // 步骤4:构建相对音高序列 for (int i = 2, fx = 1; i <= n; i++) { fx *= ff[i]; // 累积方向 a[i] = a[i - 1] + fx * b[i]; // 计算相对音高 } // 步骤5:归一化到 $[1, n]$ 范围 int mn = inf; for (int i = 1; i <= n; i++) mn = min(mn, a[i]); for (int i = 1; i <= n; i++) a[i] -= mn - 1; // 步骤6:检查音高 $1$ 和 $N$ 的相对位置 int x = 0, y = 0; for (int i = 1; i <= n; i++) { if (a[i] == 1) x = i; else if (a[i] == n) y = i; } // 步骤7:如果顺序不对则反转 if (x > y) { for (int i = 2, fx = -1; i <= n; i++) { fx *= ff[i]; a[i] = a[i - 1] + fx * b[i]; } mn = inf; for (int i = 1; i <= n; i++) mn = min(mn, a[i]); for (int i = 1; i <= n; i++) a[i] -= mn - 1; } // 步骤8:输出答案 for (int i = 1; i <= n; i++) answer(i, a[i]); }算法步骤详解
1.数据收集
-
b[i]:相邻元素 和 的音高差绝对值
-
c[i]:三个连续元素 , , 的极差
2.单调性判断
对于位置 :
-
如果 ,说明 与 同向变化
-
否则说明方向改变
3.序列构建
从位置 开始,根据方向因子 ff[i] 累积计算相对音高:

或者更精确地表示为:

其中 是累积的方向因子,取值为 或 。
4.范围调整
将相对音高平移到 范围内。
5.顺序验证
确保音高 在音高 的左边,否则反转整个序列。
复杂度分析
-
查询次数: 次
-
时间复杂度:
-
空间复杂度:
正确性证明
-
该算法基于以下关键性质:
-
相邻差值确定了元素间的相对距离
-
三元素查询揭示了单调性变化
题目保证音高 在音高 的左边,为最终调整提供了依据
算法在 次查询内必定能确定整个排列,满足题目要求的 次查询限制()。
-
- 1
信息
- ID
- 4881
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 19
- 已通过
- 1
- 上传者