校內集訓 miku set模擬冒泡排序 逆序對
阿新 • • 發佈:2018-11-04
冒泡排序 log urn iter 序列 swa 我們 pri esp
題意
- 給你一個長為\(n\)的序列,進行\(m\)次操作,每次對一個區間進行排序,求最後的序列\((n <= 1500, m <= 1e6)\)
這道題目思維難度挺大的
對於一個序列,排序的本質就是消除裏面的所有逆序對
考慮冒泡排序的過程,每次也是交換\(a[i]>a[i+1]\)這個逆序對
這樣子交換最多有\(n^2\)次
那麽我們可以用一個數據結構模擬冒泡排序交換逆序對這個過程
用一個\(set\)維護所有逆序對的位置
每次暴力刪除區間內所有逆序對
再把新產生的逆序對加入\(set\)
復雜度\(O((n^2+m)\log n)\)
Codes
#include <set> #include <cstdio> using namespace std; const int N = 1500 + 10; set<int> S; set<int>::iterator it; int a[N], n, q, L, R; int main() { //freopen("miku.in", "r", stdin); //freopen("miku.out", "w", stdout); scanf("%d%d%d%d", &n, &q, &L, &R); for (int i = 1; i <= n; ++ i) scanf("%d", &a[i]); for (int i = 1; i < n; ++ i) if (a[i] > a[i + 1]) S.insert(i); S.insert(n), a[n + 1] = 2e9; while (q --) { int l, r; scanf("%d%d", &l, &r); for (; *(it = S.lower_bound(l)) < r; S.erase(it ++)) { swap(a[*it], a[*it + 1]); if(a[*it - 1] > a[*it]) S.insert(*it - 1); if(a[*it + 1] > a[*it + 2]) S.insert(*it + 1); } } for (int i = L; i <= R; ++ i) printf("%d%c", a[i], i == R ? ‘\n‘ : ‘ ‘); return 0; }
校內集訓 miku set模擬冒泡排序 逆序對