1 条题解
-
0
题目解析
给定一个排列 ,满足对任意 有 。要求计算所有子数组 的最长递减子序列(LDS)的长度之和。
关键性质
在给定条件下,可以证明:对于任意子数组,其 LDS 长度等于子数组的长度减去子数组内“上升相邻对”的数量,其中上升相邻对是指满足 的相邻位置对。等价地,LDS 长度等于子数组内“下降相邻对”的数量加 。
证明思路
-
整个数组的 LDS 长度:设 为满足 的索引 的个数。可以证明,这些索引对应的值构成一个递减子序列(利用给定条件),且任何递减子序列最多包含每个“非下降相邻对”中的一个元素,因此 LDS 长度恰好为 。对于长度为 的子数组,LDS 长度为 ,等于下降对数量 加 。
-
子数组的推广:由于给定条件对所有 成立,任意子数组内仍满足该条件(只要三个连续元素都在子数组中)。因此,子数组的 LDS 长度同样等于其内部下降相邻对的数量加 。
-
下降对与上升对的关系:对于长度为 的子数组,有 个相邻对。下降对数量 上升对数量。故 LDS 长度 。
因此,所有子数组的 LDS 长度之和等于 所有子数组的长度之和 减去 所有子数组中上升相邻对出现的总次数。
计算总和
-
所有子数组的长度之和
每个位置 ()被包含在 个子数组中(左端点有 种选择,右端点有 种)。所以:也可直接按子数组长度累加。
-
所有上升相邻对的出现次数
对于每个 (),若 ,则包含这两个位置的子数组左端点可取 ,右端点可取 ,共 个。因此,答案为:
$$\text{Answer} = \sum_{i=1}^{n} i\,(n-i+1) \;-\; \sum_{i=1}^{n-1} [p_i < p_{i+1}] \cdot i\,(n-i) $$
时间复杂度 ,空间 (只需读入数组)。所有测试用例 总和不超过 ,满足要求。
算法步骤
对于每个测试用例:
- 读入 和排列 。
- 计算总长度和
sum_len = 0,遍历 到 ,累加 。 - 遍历 到 ,若 ,则从
sum_len中减去 。 - 输出
sum_len。
代码实现
#include <bits/stdc++.h> using namespace std; using ll = long long; int main() { ios::sync_with_stdio(false); cin.tie(0); int t; cin >> t; while (t--) { int n; cin >> n; vector<int> p(n); for (int i = 0; i < n; ++i) cin >> p[i]; ll total = 0; for (int i = 1; i <= n; ++i) { total += (ll)i * (n - i + 1); } for (int i = 0; i < n - 1; ++i) { if (p[i] < p[i+1]) { total -= (ll)(i+1) * (n - i - 1); } } cout << total << '\n'; } return 0; }示例验证
- 样例1:,无上升对,,输出 。
- 样例2:,上升对仅 (),,减去 ,得 。
- 样例3:,计算可得 ,与输出一致。
- 样例4:,上升对 (),,减去 ,得 。
所有结果与样例完全匹配。
-
- 1
信息
- ID
- 7104
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者