洛谷 P7714 排列排序
阿新 • • 發佈:2021-07-12
P7714 排列排序
按升序排序,即對於 \(1\) 到 \(n\) 的每一個 \(i\),都有 \(p_i=i\)。
1 P7714 排列排序
2 題目描述
時間限制 \(1s\) | 空間限制 \(128M\)
小 \(E\) 給你一個長度為 \(n\) 的排列 \(p_1,p_2, \cdots ,p_n\)。小 \(E\) 想要把它排序。
小 \(E\) 每次可以花區間長度,即 \(r-l+1\) 的代價,選擇排列中的任意一段區間 \([l,r]\),並將 \([l,r]\) 從小到大排序。
現在你可以讓他進行若干次這個操作,直到 \(p\) 中元素的值從 \(1\) 到 \(n\)
小 \(E\) 問你,他花的代價最少為多少?
資料範圍:\(1≤T,∑n≤10^6\)
3 題解
我們發現:有一些在正確位置的數不需要被排序。那麼具體是哪些呢?
我們可以考慮將每個在正確位置的數看成分界點。如果陣列的開頭與當前分界點之間的數恰好對應的是 \(1\) 到當前分界點之間的數,只不過順序不同,那麼我們就可以不把這個分界點計入答案中。
我們如何檢查陣列的開頭與當前分解點之間的數是否恰好對應的是 \(1\) 到當前分界點之間的數呢?我們發現,由於陣列是 \(1\) 到 \(n\) 之間的排列,所以每一個數都只出現了一次。也就是說,如果當前數開頭到分界點之間的最大值等於分界點,那麼這一段就一定是某段排列。
4 程式碼(空格警告):
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; const int N = 1e6 + 10; int n, maxn, T, cnt; int a[N]; int read() { int x = 0, f = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); } while (c >= '0' && c <= '9') { x = (x << 1) + (x << 3) + (c ^ 48); c = getchar(); } return x * f; } int main() { T = read(); while (T--) { maxn = 0, cnt = 0; n = read(); for (int i = 1; i <= n; i++) a[i] = read(); for (int i = 1; i <= n; i++) { maxn = max(a[i], maxn); if (a[i] == i && i == maxn) cnt++; } printf("%d\n", n - cnt); } return 0; }