P4375 [USACO18OPEN]Out of Sorts G 題解
阿新 • • 發佈:2021-10-27
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