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

YYen
**搬运于
2025-08-24 22:32:25,当前版本为作者最后更新于2021-07-12 00:42:05,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
思路:双指针
比赛时候看到这个题脑海闪过双指针,测试了几组例子发现都没问题,交了就AC了,说一下思路:
先约定,左指针 初始值为 ,以及右指针 。
从左往右逐个元素进行枚举,
①、如果某个元素值与下标相同,代表该元素处于正确的位置,左指针 加 枚举下一个元素。
②、不同则代表该元素处于不正确的位置,此时左指针 指向的下标即为排序的左端点,因此生成右指针 ,初始化为 ,开始往后查找排序的右端点。该查找过程还需要一个 变量来维护双指针范围内的区间最大值,当右指针 不停向右滑动,直至指向的下标大于等于区间最大值时,右指针 指向的下标即为排序的右端点(这个道理应该是显然的,因为如果右指针 指向的下标不如区间最大值 大,代表还没找到区间最大值的对应位置,还需要进一步扩大区间长度,所以右指针 还需要继续右移)。此时排序区间长度为 。更新左指针 为右指针 的下一个位置,重复以上过程,直至全部元素枚举完毕。
最终时间复杂度为 。
代码
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; int a[1000005]; int main() { int T; cin >> T; while (T--) { int n, ans = 0; scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); int i = 1; while (i <= n) { if (a[i] == i) // 相同 i++; else // 不同 { int maxv = a[i]; int j = i + 1; maxv = max(maxv, a[j]); while (maxv > j) { j++; maxv = max(maxv, a[j]); } ans += j - i + 1; i = j + 1; } } cout << ans << endl; } return 0; }
- 1
信息
- ID
- 6782
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 2
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者