[USACO18OPEN] Out of Sorts P 题解
前言
题目链接:洛谷。
其他题解十分生硬地给出了 t[]
的定义,本题解按照解题思路,层层递进,自然得出题目解法。
题意简述
以下是冒泡排序的一轮:
void bubble_sort(int val[], int l, int r) { for (int i = l; i < r; ++i) if (val[i] > val[i + 1]) swap(val[i], val[i + 1]); }
定义
以下是一个基于分治和冒泡排序的排序算法:
void qsort(int val[], int l, int r){ if (l == r) return; do { bubble_sort(val, l, r); work_cnt += r - l + 1; } while (!check(val, l, r)); // check(val, l, r) 返回 val[l~r] 中是否存在「分割点」 divide_and_qsort_each_piece(val, l, r); // 将 val[l~r] 按照「分割点」分割成若干子问题,并递归调用 qsort }
给你长度为 qsort(a, 1, n)
后,全局变量 work_cnt
的值。
题目分析
显然我们需要分析冒泡排序的性质。
一轮冒泡排序后,肯定会产生一个「分割点」。这是由于一轮冒泡排序后,序列中的最大值被冒泡到了最右侧,所以产生了一个「分割点」。所以那个 do...while
实际没有用处。
然后发现整个序列在排序过程中比较鬼畜,难以发现性质。于是考虑转变计数视角,求每一个元素被 bubble_sort
了多少次,答案就是每个元素答案之和。
对于一个元素,只要它没有到达最终位置,它会一直被 bubble_sort
,这在时间轴上体现为一段前缀,我们只要求出在什么时候这个元素不会被 bubble_sort
即可。发现,每个元素唯一的递归出口 l == r
的实际含义为,该元素左右两侧都出现了「分割点」,于是问题似乎可以被进一步规约到每一个「分割点」出现的时刻。
一个「分割点」出现,当该在它左侧的元素都在它左侧,该在它右侧的元素都在它右侧了。这么想是因为我们冒泡排序的经典思考方式,关注于每一个元素的移动。我们有一个经典结论:
经典结论:
对于一个元素,倘若它想要向左移动,它在一轮冒泡中会恰向左移动一个位置。
考虑在一轮冒泡中,它会且只会和其左侧的最大值 swap
,然后向左移动一个位置。
所以我们考虑在某一个「分割点」右侧的元素,什么时候到这个「分割点」左侧。所需的冒泡轮数,根据我们的结论,就是它到「分割点」的距离。那么对于所有在它右侧且想要跑到它左侧的元素,求出位置最靠右的元素的位置,即可求出这个「分割点」出现的时间。
接下来随便求了。给出一种可能的实现方式:设
时间复杂度
代码
实际实现起来很短。
#include <cstdio> #include <algorithm> using namespace std; const int N = 100010; int n, a[N], b[N], t[N]; long long ans; signed main() { scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); b[i] = i; } sort(b + 1, b + n + 1, [] (int x, int y) -> bool { if (a[x] == a[y]) return x < y; // notice this detail return a[x] < a[y]; }); t[0] = 1; for (int i = 1; i <= n; ++i) { b[i] = max(b[i], b[i - 1]); // mxR[i] t[i] = b[i] - i; if (t[i] <= 0) t[i] = 1; } for (int i = 1; i <= n; ++i) ans += max(t[i], t[i - 1]); printf("%lld", ans); return 0; }
本文作者:XuYueming,转载请注明原文链接:https://www.cnblogs.com/XuYueming/p/18705237。
若未作特殊说明,本作品采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】