1. 程式人生 > 其它 >洛谷 P7714 排列排序

洛谷 P7714 排列排序

P7714 排列排序

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\)

按升序排序,即對於 \(1\)\(n\) 的每一個 \(i\),都有 \(p_i=i\)

\(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;
}

歡迎關注