1. 程式人生 > 其它 >P4375 [USACO18OPEN]Out of Sorts G 題解

P4375 [USACO18OPEN]Out of Sorts G 題解

Description

洛谷傳送門

Solution

一道很巧妙的結論題。

我們觀察到題目中是一個雙向氣泡排序。然後問你要進行多少輪才能排好序。

我們首先對於原陣列進行離散化。

考慮氣泡排序的過程(假設當前陣列未排好序):

  • 第一次:找出一個最大值放到最後面。

    對於位置 \(x\),冒泡之後一定有一個大於 \(x\) 的數被放到了 \(x\) 後面。

  • 第二次:找出一個最小值放到最前面。

    同理,對於位置 \(x\),一定有一個小於等於 \(x\) 的值放到了 \(x\) 的前面。

這樣一來,相當於把 \(x\) 前面的一個大於它的數和它後面一個小於等於它的數交換了。

因此,結論就是:$$ans = max(ans, x 前面大於 x 的數的個數)$$

用樹狀陣列維護一下即可。

Code

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

const int N = 1e5 + 10;
int n;
struct node{
    int pos, val;
    bool operator < (const node &b) const{
        return val != b.val ? val < b.val : pos < b.pos;
    }
}p[N];
int c[N];

inline void update(int x){
    for(; x <= n; x += x & (-x))
        c[x]++;
}

inline int query(int x){
    int res = 0;
    for(; x; x -= x & (-x))
        res += c[x];
    return res;
}

int main(){
    n = read();
    for(int i = 1; i <= n; ++i){
        p[i].val = read();
        p[i].pos = i;
    }
    sort(p + 1, p + 1 + n);
    int ans = 1;
    for(int i = 1; i <= n; ++i){
        update(p[i].pos);
        ans = max(ans, i - query(i));
    }
    printf("%d\n", ans);
    return 0;
}

End

本文來自部落格園,作者:xixike,轉載請註明原文連結:https://www.cnblogs.com/xixike/p/15472038.html