Problem:
バブルソート(Bubble Sort)
バブルソートとは，列をソートするアルゴリズムの 1 つである．長さ
N
の数列
A
を昇順にソートしたいとしよう．バブルソートは，隣り合う 2 つの数で大小関係が崩れているものがあれば，それらの位置を交換する．これを，数列を前から順に走査しながら行う．すなわち，
A
i
>
A
i+1
となっている場所があれば，その 2 数を交換するということを，
i
= 1, 2, ... ,
N
− 1 に対してこの順で行うのが 1 回の走査である．この走査を
N
− 1 回繰り返すことで，数列を昇順にソートできることが知られている．
数列
A
のバブルソートによる交換回数とは，数列
A
に上記のアルゴリズムを適用した時に，整数の交換が行われる回数である．（バブルソートとして知られるアルゴリズム及び実装には，ループの順番や範囲，及び終了条件など，細かな差異がある場合がある．ただし，同じ数列に適用した際の整数の交換回数はそれらの差異により変化しないことが知られている．）
例えば，以下のプログラムは長さ
n
の整数の配列
a
をバブルソートによりソートする関数を C 言語で記述したものである．
void bubble_sort(int *a, int n) {
  int i, j;
  for (i = 0; i < n - 1; ++i) {
    for (j = 0; j < n - 1; ++j) {
      if (a[j] > a[j + 1]) {
        /* 以下3 行が1 回の整数の交換に相当*/
        int x = a[j];
        a[j] = a[j + 1];
        a[j + 1] = x;
      }
    }
 }
}
課題
長さ
N
の数列
A
が与えられる．数列
A
の任意の場所の 2 つの整数を 1 回だけ交換した数列
A'
を作るとする．数列
A'
のバブルソートによる交換回数の最小値を求めるプログラムを作成せよ．（最初に交換する2つの整数は必ずしも隣り合っている必要はないことに注意せよ．）
制限
1 ≤
N
≤ 100 000      数列
A
の長さ
1 ≤
A
i
≤ 1 000 000 000     数列
A
に含まれる数字の大きさ
入力
標準入力から以下のデータを読み込め．
1 行目には，整数
N
が書かれている．
N
は数列
A
の長さを表す．
続く
N
行のうちの
i
行目(1 ≤
i
≤
N
) には，整数
A
i
が書かれている．これは数列
A
の
i
番目の整数を表す．
出力
標準出力に，数列
A'
のバブルソートによる交換回数の最小値を表す整数を 1 行で出力せよ．
採点基準
採点用データのうち，配点の10%分については，
N
≤ 1 000 を満たし，任意の
i, j
(1 ≤
i
<
j
≤
N
) について
A
i
≠
A
j
を満たす．
採点用データのうち，配点の30%分については，
N
≤ 5 000 を満たし，任意の
i, j
(1 ≤
i
<
j
≤
N
) について
A
i
≠
A
j
を満たす．
採点用データのうち，配点の80%分については，任意の
i, j
(1 ≤
i
<
j
≤
N
) について
A
i
≠
A
j
を満たす．
入出力例
入力例 1
5
10
3
6
8
1
出力例 1
0
数列
A
の最初の 10 と最後の 1 を交換することにすると，数列
A'
はソート済みの列となり，バブルソートの交換回数は 0 となる．
入力例 2
5
3
1
7
9
5
出力例 2
2
数列
A
の 3 番目の 7 と最後の 5 を交換することで，数列
A'
は 3,1,5,9,7 となる．
A'
のバブルソートによる交換回数は 2 である．
入力例 3
3
1
2
3
出力例 3
1
最初から数列
A
がソートされている場合でも，数列
A'
を作る際に交換を行わなければならない．
問題文と自動審判に使われるデータは、
情報オリンピック日本委員会
が作成し公開している問題文と採点用テストデータです。

Submitted solutions:

code_snippet: #include <cstdio>
#include <algorithm>
#include <vector>

using namespace std;

// 配列のサイズと配列データ
int b[110000];
int z[110000];
long long bit[110000];

// BIT (Binary Indexed Tree) の範囲和を計算する関数
long long sum(int a, int b) {
    if(a) return sum(0, b) - sum(0, a-1);
    long long ret = 0;
    for(; b >= 0; b = (b & (b + 1)) - 1) ret += bit[b];
    return ret;
}

// BIT (Binary Indexed Tree) に値を追加する関数
void add(int a, int b) {
    for(; a < 110000; a |= a + 1) bit[a] += b;
}

// セグメントツリー用の配列
int segtree[262144];
int lx[110000];
int ly[110000];
int rx[110000];
int ry[110000];

// セグメントツリーに範囲を指定して値を追加する関数
void add2(int a, int b, int c, int d, int e, int f) {
    if(d < a || b < c) return;
    if(c <= a && b <= d) {
        segtree[e] += f;
    } else {
        add2(a, (a + b) / 2, c, d, e * 2, f);
        add2((a + b) / 2 + 1, b, c, d, e * 2 + 1, f);
    }
    if(e > 1 && ((segtree[e] != 0 && segtree[e ^ 1] != 0) || segtree[e] > 0 || segtree[e ^ 1] > 0)) {
        int t = max(segtree[e], segtree[e ^ 1]);
        segtree[e / 2] += t;
        segtree[e ^ 1] -= t;
        segtree[e] -= t;
    }
}

// セグメントツリーに範囲を指定して最大値を取得する関数
int query(int a, int b, int c, int d, int e, int f) {
    if(d < a || b < c) return -99999999;
    if(c <= a && b <= d) return segtree[e] + f;
    return max(query(a, (a + b) / 2, c, d, e * 2, f + segtree[e]), query((a + b) / 2 + 1, b, c, d, e * 2 + 1, f + segtree[e]));
}

int L[110000];
int R[110000];
pair<int, int> yp[110000];

int main() {
    int a;
    scanf("%d", &a);
    for(int i = 0; i < a; i++) scanf("%d", b + i);

    bool chk = true;
    bool same = false;
    for(int i = 0; i < a - 1; i++) if(b[i] < b[i - 1]) chk = false;
    for(int i = 0; i < a - 1; i++) if(b[i] == b[i - 1]) same = true;
    if(chk) {
        if(same) printf("0\n");
        else printf("1\n");
        return 0;
    }

    for(int i = 0; i < a; i++) {
        z[i] = b[i];
        yp[i] = make_pair(b[i], i);
    }
    std::sort(yp, yp + a);
    std::sort(z, z + a);
    long long ans = 0;
    for(int i = 0; i < a; i++) {
        int at = lower_bound(z, z + a, b[i]) - z;
        if(at < a - 1) ans += sum(at + 1, a - 1);
        add(at, 1);
    }

    int tmp = 0;
    int ls = 0;
    int rs = 0;
    for(int i = 0; i < a; i++) {
        if(tmp < b[i]) {
            L[i] = 1;
            tmp = b[i];
            lx[ls] = i;
            ly[ls++] = tmp;
        }
    }

    tmp = 1000000007;
    for(int i = a - 1; i >= 0; i--) {
        if(tmp > b[i] && L[i] == 0) {
            R[i] = 1;
            tmp = b[i];
        }
    }

    for(int i = 0; i < a; i++) {
        if(R[i]) {
            rx[rs] = i;
            ry[rs++] = b[i];
        }
    }

    int ret = 0;
    int rm = 0;
    int ypat = 0;
    for(int i = 0; i < a; i++) {
        if(R[i]) {
            int nx = b[i];
            int tmp = 0;
            while(ypat < a && yp[ypat].first < nx) {
                int ind = yp[ypat].second;
                if(!L[ind] && !R[ind]) {
                    int to = lower_bound(ly, ly + ls, b[ind]) - ly;
                    int rim = lower_bound(lx, lx + ls, ind) - lx - 1;
                    if(to <= rim) add2(0, 131071, to, rim, 1, -1);
                    if(b[ind] == ly[to]) to++;
                    if(to <= rim) add2(0, 131071, to, rim, 1, -1);
                }
                ypat++;
            }
            int cp = ypat;
            while(cp < a && yp[cp].first == nx) {
                int ind = yp[cp].second;
                if(!L[ind] && !R[ind]) {
                    int to = lower_bound(ly, ly + ls, b[ind]) - ly;
                    int rim = lower_bound(lx, lx + ls, ind) - lx - 1;
                    if(to <= rim) add2(0, 131071, to, rim, 1, -1);
                }
                cp++;
            }
            int at = lower_bound(lx, lx + ls, i) - lx - 1;
            int at2 = upper_bound(ly, ly + ls, b[i]) - ly;
            if(at2 <= at) {
                tmp = query(0, 131071, at2, at, 1, 0);
                ret = max(ret, tmp);
            }
            while(ypat < a && yp[ypat].first == nx) {
                int ind = yp[ypat].second;
                if(!L[ind] && !R[ind]) {
                    int to = lower_bound(ly, ly + ls, b[ind]) - ly;
                    int rim = lower_bound(lx, lx + ls, ind) - lx - 1;
                    if(b[ind] == ly[to]) to++;
                    if(to <= rim) add2(0, 131071, to, rim, 1, -1);
                }
                ypat++;
            }
        } else if(!L[i]) {
            int to = lower_bound(ly, ly + ls, b[i]) - ly;
            int rim = lower_bound(lx, lx + ls, i) - lx - 1;
            if(to <= rim) add2(0, 131071, to, rim, 1, 1);
            if(b[i] == ly[to]) to++;
            if(to <= rim) add2(0, 131071, to, rim, 1, 1);
        }
    }

    printf("%lld\n", ans - ret - 1);
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 8452
final_rank: 1

code_snippet: #include <bits/stdc++.h>
#define err(args...) {}
#ifdef DEBUG
#include "_debug.cpp"
#endif
using namespace std;
using ll = long long;
using ld = long double;
template <typename T> using lim = numeric_limits<T>;
template <typename T> istream& operator>>(istream& is, vector<T>& a) { for(T& x : a) { is >> x; } return is; }
template <typename X, typename Y> istream& operator>>(istream& is, pair<X, Y>& p) { return is >> p.first >> p.second; }
template <typename T> struct monoid {
    const T identity;
    const function<T(T, T)> combine;
};
template <typename T, typename D> struct segtree {
    static constexpr int st_size(int size) { return (4 << __lg(size - 1)) - 1; }
    using Type = T;
    using DeltaType = D;
    const int size;
    const monoid<T> st_m;
    const monoid<D> delta_m;
    template <typename signature> using f = const function<signature>;
    f<T(T, D, int, int)> lazy_query;
    vector<T> st;
    vector<D> delta;
    vector<bool> is_lazy;
    int L(int p) { return (p << 1) + 1; }
    int R(int p) { return (p << 1) + 2; }
    int m(int s, int e) { return (s + e) >> 1; }
    void pull(int p, int s, int e) {
        st[p] = st_m.combine(get_val(L(p), s, m(s, e)), get_val(R(p), m(s, e), e));
    }
    void lazy(int p, D v) {
        delta[p] = delta_m.combine(delta[p], v), is_lazy[p] = true;
    }
    void unlazy(int p, int s, int e) {
        if(is_lazy[p]) {
            if(e - s > 1) lazy(L(p), delta[p]), lazy(R(p), delta[p]);
            delta[p] = delta_m.identity, is_lazy[p] = false;
            pull(p, s, e);
        }
    }
    T get_val(int p, int s, int e) {
        return is_lazy[p] ? lazy_query(st[p], delta[p], s, e) : st[p];
    }
    T build(const vector<T>& a, int p, int s, int e) {
        if(e - s > 1) {
            return st[p] = st_m.combine(build(a, L(p), s, m(s, e)), build(a, R(p), m(s, e), e));
        } else {
            return st[p] = a[s];
        }
    }
    segtree(const vector<T>& a, const monoid<T>& st_m, const monoid<D>& delta_m, f<T(T, D, int, int)>& lazy_query)
    : size(a.size()), st_m(st_m), delta_m(delta_m), lazy_query(lazy_query),
    st(st_size(size)), delta(st_size(size), delta_m.identity), is_lazy(st_size(size)) {
        build(a, 0, 0, size);
    }
    segtree(int size, const monoid<T>& st_m, const monoid<D>& delta_m, f<T(T, D, int, int)>& lazy_query)
    : segtree(vector<T>(size + 1, st_m.identity), st_m, delta_m, lazy_query) {}
    T query(int l, int r, int p, int s, int e) {
        if(l <= s and e <= r) {
            return get_val(p, s, e);
        } else if(r <= s or e <= l) {
            return st_m.identity;
        } else {
            unlazy(p, s, e);
            return st_m.combine(query(l, r, L(p), s, m(s, e)), query(l, r, R(p), m(s, e), e));
        }
    }
    T query(int l, int r, bool inclusive) {
        assert(l <= r);
        return query(l, r + inclusive, 0, 0, size);
    }
    T query(int i) { return query(i, i, true); }
    void update(int l, int r, D v, int p, int s, int e) {
        if(l <= s and e <= r) {
            lazy(p, v);
        } else if(not (r <= s or e <= l)) {
            unlazy(p, s, e);
            update(l, r, v, L(p), s, m(s, e)), update(l, r, v, R(p), m(s, e), e);
            pull(p, s, e);
        }
    }
    void update(int l, int r, D v, bool inclusive) {
        assert(l <= r);
        update(l, r + inclusive, v, 0, 0, size);
    }
    void update(int i, D v) { update(i, i, v, true); }
    void reset() {
        fill(st.begin(), st.end(), st_m.identity);
        fill(delta.begin(), delta.end(), delta_m.identity);
        fill(is_lazy.begin(), is_lazy.end(), false);
    }
    friend ostream& operator<<(ostream& os, segtree& t) {
        os << "[";
        for(int i = 0; i <= t.size; i++) {
            if(i != 0) os << ", ";
            os << t.query(i);
        }
        return os << "]";
    }
};
template <typename T> struct rmq_segtree : public segtree<T, T> {
    rmq_segtree(int size) : segtree<T, T>(
        size, 
        {0, [](const T& x, const T& y) { return max(x, y); }}, 
        {0, plus<T>()},
        [](const T& st, const T& delta, int, int) { return st + delta; }) {}
};
// NOTE: one-indexed
template <typename T> struct bit {
    const int n;
    vector<T> t;
    bit(int n) : n(n), t(n + 1) {}
    void add(int i, T value) {
        for(int j = i; j <= n; j += j & -j) {
            t[j] += value;
        }
    }
    T sum(int i) {
        T res = 0;
        for(int j = i; j > 0; j -= j & -j) {
            res += t[j];
        }
        return res;
    }
    T sum(int L, int R) {
        return sum(R) - sum(L - 1);
    }
    void clear() {
        fill(t.begin(), t.end(), 0);
    }
    friend ostream& operator<<(ostream& os, bit& t) {
        os << "[";
        for(int i = 1; i <= t.n; i++) {
            if(i != 1) os << ", ";
            os << t.sum(i, i);
        }
        return os << "]";
    }
};
template <typename T> vector<T> compress(const vector<T>& a) {
    vector<T> vals = a;
    sort(vals.begin(), vals.end());
    vals.erase(unique(vals.begin(), vals.end()), vals.end());
    vector<T> compressed = a;
    for(T& val : compressed) {
        val = lower_bound(vals.begin(), vals.end(), val) - vals.begin() + 1;
    }
    return compressed;
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin >> n;
    vector<int> a(n);
    cin >> a;
    a = compress(a);
    bit<int> present_values(n);
    ll swaps = 0;
    for(int x : a) {
        swaps += present_values.sum(x + 1, n);
        present_values.add(x, 1);
    }
    present_values.clear();
    vector<int> is_top_left_candidate(n), is_bottom_right_candidate(n);
    for(int i = 0; i < n; i++) {
        is_top_left_candidate[i] = present_values.sum(a[i], n) == 0;
        present_values.add(a[i], 1);
    }
    present_values.clear();
    for(int i = n - 1; i >= 0; i--) {
        is_bottom_right_candidate[i] = present_values.sum(a[i]) == 0;
        present_values.add(a[i], 1);
    }
    present_values.clear();
    ll ans = swaps + (set<int>(a.begin(), a.end()).size() == n);
    rmq_segtree<int> top_left_contribution(n);
    vector<int> top_left_vals;
    multiset<tuple<int, int, int, int>> to_remove;
    for(int i = 0; i < n; i++) {
        if(is_bottom_right_candidate[i]) {
            int L = upper_bound(top_left_vals.begin(), top_left_vals.end(), a[i]) - top_left_vals.begin();
            if(L < top_left_vals.size()) {
                while(not to_remove.empty() and get<0>(*to_remove.begin()) < a[i]) {
                    int aj, L_ge, L_gt, R;
                    tie(aj, L_ge, L_gt, R) = *to_remove.begin();
                    top_left_contribution.update(L_ge, R, -1, false);
                    top_left_contribution.update(L_gt, R, -1, false);
                    to_remove.erase(to_remove.begin());
                }
                for(auto it = to_remove.begin(); it != to_remove.end() and get<0>(*it) == a[i]; it++) {
                    int aj, L_ge, L_gt, R;
                    tie(aj, L_ge, L_gt, R) = *it;
                    top_left_contribution.update(L_ge, R, -1, false);
                }
                ans = min(ans, swaps - top_left_contribution.query(L, n, false) - 1);
                for(auto it = to_remove.begin(); it != to_remove.end() and get<0>(*it) == a[i]; it++) {
                    int aj, L_ge, L_gt, R;
                    tie(aj, L_ge, L_gt, R) = *it;
                    top_left_contribution.update(L_ge, R, +1, false);
                }
            }
        } else if(is_top_left_candidate[i]) {
            top_left_vals.push_back(a[i]);
        } else {
            int L_ge = lower_bound(top_left_vals.begin(), top_left_vals.end(), a[i]) - top_left_vals.begin();
            int L_gt = upper_bound(top_left_vals.begin(), top_left_vals.end(), a[i]) - top_left_vals.begin();
            top_left_contribution.update(L_ge, top_left_vals.size(), 1, false);
            top_left_contribution.update(L_gt, top_left_vals.size(), 1, false);
            to_remove.insert(make_tuple(a[i], L_ge, L_gt, top_left_vals.size()));
        }
    }
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 12968
final_rank: 4

code_snippet: #include <bits/stdc++.h>
#define err(args...) {}
#ifdef DEBUG
#include "_debug.cpp"
#endif
using namespace std;
using ll = long long;
using ld = long double;
template <typename T> using lim = numeric_limits<T>;
template <typename T> istream& operator>>(istream& is, vector<T>& a) { for(T& x : a) { is >> x; } return is; }
template <typename X, typename Y> istream& operator>>(istream& is, pair<X, Y>& p) { return is >> p.first >> p.second; }
template <typename T> struct monoid {
    const T identity;
    const function<T(T, T)> combine;
};
template <typename T, typename D> struct segtree {
    static constexpr int st_size(int size) { return (4 << __lg(size - 1)) - 1; }
    using Type = T;
    using DeltaType = D;
    const int size;
    const monoid<T> st_m;
    const monoid<D> delta_m;
    template <typename signature> using f = const function<signature>;
    f<T(T, D, int, int)> lazy_query;
    vector<T> st;
    vector<D> delta;
    vector<bool> is_lazy;
    int L(int p) { return (p << 1) + 1; }
    int R(int p) { return (p << 1) + 2; }
    int m(int s, int e) { return (s + e) >> 1; }
    void pull(int p, int s, int e) {
        st[p] = st_m.combine(get_val(L(p), s, m(s, e)), get_val(R(p), m(s, e), e));
    }
    void lazy(int p, D v) {
        delta[p] = delta_m.combine(delta[p], v), is_lazy[p] = true;
    }
    void unlazy(int p, int s, int e) {
        if(is_lazy[p]) {
            if(e - s > 1) lazy(L(p), delta[p]), lazy(R(p), delta[p]);
            delta[p] = delta_m.identity, is_lazy[p] = false;
            pull(p, s, e);
        }
    }
    T get_val(int p, int s, int e) {
        return is_lazy[p] ? lazy_query(st[p], delta[p], s, e) : st[p];
    }
    T build(const vector<T>& a, int p, int s, int e) {
        if(e - s > 1) {
            return st[p] = st_m.combine(build(a, L(p), s, m(s, e)), build(a, R(p), m(s, e), e));
        } else {
            return st[p] = a[s];
        }
    }
    segtree(const vector<T>& a, const monoid<T>& st_m, const monoid<D>& delta_m, f<T(T, D, int, int)>& lazy_query)
    : size(a.size()), st_m(st_m), delta_m(delta_m), lazy_query(lazy_query),
    st(st_size(size)), delta(st_size(size), delta_m.identity), is_lazy(st_size(size)) {
        build(a, 0, 0, size);
    }
    segtree(int size, const monoid<T>& st_m, const monoid<D>& delta_m, f<T(T, D, int, int)>& lazy_query)
    : segtree(vector<T>(size + 1, st_m.identity), st_m, delta_m, lazy_query) {}
    T query(int l, int r, int p, int s, int e) {
        if(l <= s and e <= r) {
            return get_val(p, s, e);
        } else if(r <= s or e <= l) {
            return st_m.identity;
        } else {
            unlazy(p, s, e);
            return st_m.combine(query(l, r, L(p), s, m(s, e)), query(l, r, R(p), m(s, e), e));
        }
    }
    T query(int l, int r, bool inclusive) {
        assert(l <= r);
        return query(l, r + inclusive, 0, 0, size);
    }
    T query(int i) { return query(i, i, true); }
    void update(int l, int r, D v, int p, int s, int e) {
        if(l <= s and e <= r) {
            lazy(p, v);
        } else if(not (r <= s or e <= l)) {
            unlazy(p, s, e);
            update(l, r, v, L(p), s, m(s, e)), update(l, r, v, R(p), m(s, e), e);
            pull(p, s, e);
        }
    }
    void update(int l, int r, D v, bool inclusive) {
        assert(l <= r);
        update(l, r + inclusive, v, 0, 0, size);
    }
    void update(int i, D v) { update(i, i, v, true); }
    void reset() {
        fill(st.begin(), st.end(), st_m.identity);
        fill(delta.begin(), delta.end(), delta_m.identity);
        fill(is_lazy.begin(), is_lazy.end(), false);
    }
    friend ostream& operator<<(ostream& os, segtree& t) {
        os << "[";
        for(int i = 0; i <= t.size; i++) {
            if(i != 0) os << ", ";
            os << t.query(i);
        }
        return os << "]";
    }
};
template <typename T> struct rmq_segtree : public segtree<T, T> {
    rmq_segtree(int size) : segtree<T, T>(
        size, 
        {0, [](const T& x, const T& y) { return max(x, y); }}, 
        {0, plus<T>()},
        [](const T& st, const T& delta, int, int) { return st + delta; }) {}
};
// NOTE: one-indexed
template <typename T> struct bit {
    const int n;
    vector<T> t;
    bit(int n) : n(n), t(n + 1) {}
    void add(int i, T value) {
        for(int j = i; j <= n; j += j & -j) {
            t[j] += value;
        }
    }
    T sum(int i) {
        T res = 0;
        for(int j = i; j > 0; j -= j & -j) {
            res += t[j];
        }
        return res;
    }
    T sum(int L, int R) {
        return sum(R) - sum(L - 1);
    }
    void clear() {
        fill(t.begin(), t.end(), 0);
    }
    friend ostream& operator<<(ostream& os, bit& t) {
        os << "[";
        for(int i = 1; i <= t.n; i++) {
            if(i != 1) os << ", ";
            os << t.sum(i, i);
        }
        return os << "]";
    }
};
template <typename T> vector<T> compress(const vector<T>& a) {
    vector<T> vals = a;
    sort(vals.begin(), vals.end());
    vals.erase(unique(vals.begin(), vals.end()), vals.end());
    vector<T> compressed = a;
    for(T& val : compressed) {
        val = lower_bound(vals.begin(), vals.end(), val) - vals.begin() + 1;
    }
    return compressed;
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin >> n;
    vector<int> a(n);
    cin >> a;
    if(all_of(a.begin(), a.end(), [&](int x) { return x == a[0]; })) {
        cout << 0 << endl;
    } else {
        a = compress(a);
        bit<int> b(n), present_values(n);
        ll swaps = 0;
        for(int x : a) {
            swaps += b.sum(x + 1, n);
            b.add(x, 1);
        }
        vector<int> is_top_left_candidate(n), is_bottom_right_candidate(n);
        for(int i = 0; i < n; i++) {
            is_top_left_candidate[i] = present_values.sum(a[i] + 1, n) == 0;
            present_values.add(a[i], 1);
        }
        present_values.clear();
        for(int i = n - 1; i >= 0; i--) {
            is_bottom_right_candidate[i] = present_values.sum(a[i] - 1) == 0;
            present_values.add(a[i], 1);
        }
        present_values.clear();
        ll ans = swaps + (set<int>(a.begin(), a.end()).size() == n);
        rmq_segtree<int> top_left_contribution(n);
        vector<int> top_left_candidates_values;
        set<tuple<int, int, int>> to_remove;
        for(int i = 0; i < n; i++) {
            if(is_bottom_right_candidate[i]) {
                if(not top_left_candidates_values.empty()) {
                    while(not to_remove.empty() and get<0>(*to_remove.begin()) < a[i]) {
                        int aj, L, R;
                        tie(aj, L, R) = *to_remove.begin();
                        top_left_contribution.update(L, R, -1, false);
                        to_remove.erase(to_remove.begin());
                    }
                    ans = min(ans, swaps - 2 * top_left_contribution.query(0, n, false) - 1);
                }
            } else if(is_top_left_candidate[i]) {
                top_left_candidates_values.push_back(a[i]);
            } else {
                int j = upper_bound(top_left_candidates_values.begin(), top_left_candidates_values.end(), a[i], [&](int aj, int x) {
                    return aj < x;
                }) - top_left_candidates_values.begin();
                top_left_contribution.update(j, top_left_candidates_values.size(), 1, false);
                to_remove.insert(make_tuple(a[i], j, top_left_candidates_values.size()));
            }
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 0.7476635514018691
time_ms: 110
memory_kb: 13188
final_rank: 15

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 100005


struct Info{
	Info(){

		mid_index = 0;
		value = 0;
	}
	Info(int arg_mid_index,ll arg_value){
		mid_index = arg_mid_index;
		value = arg_value;
	}
	bool operator<(const struct Info &arg) const{

		return value > arg.value; //値の昇順(PQ)
	}

	int mid_index;
	ll value;
};

ll N;
ll A[SIZE],BIT[SIZE];
ll L_TOP[SIZE],MID[SIZE];
ll L[SIZE],R[SIZE],SAME_L_TOP[SIZE],count_table[SIZE];
bool is_L_TOP[SIZE],is_R_BOTTOM[SIZE];
vector<ll> V,R_BOTTOM;
map<ll,ll> MAP;

ll max_data[8*SIZE],add_data[8*SIZE];
ll seg_N = 1;

void add(ll loc,ll value){

	BIT[loc] += value;

	loc += loc & -loc;

	while(loc <= N){
		BIT[loc] += value;
		loc += loc & -loc;
	}
}

ll getSum(ll loc){

	ll sum = BIT[loc];

	loc -= loc & -loc;

	while(loc > 0){
		sum += BIT[loc];
		loc -= loc & -loc;
	}
	return sum;
}

ll calc(ll left,ll right){
	return getSum(right)-getSum(left-1);
}


//RAQ and RMQ
void init(ll first_N){
	while(seg_N < first_N)seg_N *= 2;
}


void add(int left,int right,ll value,int node_id,int node_left,int node_right){

	if(right < node_left || left > node_right){
		//範囲外ならreturn
		return;
	}
	else if(left <= node_left && right >= node_right){ //このノードのカバーしている区間が、更新区間の部分区間である場合

		add_data[node_id] += value; //一様に加える値を加算

		while(node_id != 0){

			node_id = (node_id-1)/2;
			max_data[node_id] = max(max_data[2*node_id+1]+add_data[2*node_id+1],max_data[2*node_id+2]+add_data[2*node_id+2]);
		}
	}else{

		add(left,right,value,2*node_id+1,node_left,(node_left+node_right)/2);
		add(left,right,value,2*node_id+2,(node_left+node_right)/2+1,node_right);
	}
}

ll getMax(int left,int right,int node_id,int node_left,int node_right){
	if(right < node_left || left > node_right)return -BIG_NUM;
	else if(left <= node_left && right >= node_right){
		return max_data[node_id]+add_data[node_id];

	}else{

		ll  left_max  = getMax(left,right,2*node_id+1,node_left,(node_left+node_right)/2);
		ll  right_max = getMax(left,right,2*node_id+2,(node_left+node_right)/2+1,node_right);
		return max(left_max,right_max)+add_data[node_id];
	}
}


int main(){

	scanf("%lld",&N);

	for(int i = 0; i < N; i++){

		scanf("%lld",&A[i]);
		V.push_back(A[i]);
	}

	sort(V.begin(),V.end());
	V.erase(unique(V.begin(),V.end()),V.end());

	for(int i = 0; i < V.size(); i++){

		MAP[V[i]] = i;
	}

	for(int i = 0; i <= V.size(); i++)BIT[i] = 0;

	ll swap_count = 0;

	for(ll i = 0; i < N; i++){
		swap_count += i-getSum(MAP[A[i]]+1);
		add(MAP[A[i]]+1,1);
	}

	if(swap_count == 0){

		for(int i = 1; i < N; i++){
			if(A[i-1] == A[i]){

				printf("0\n");
				return 0;
			}
		}

		printf("1\n");
		return 0;
	}

	ll maximum = -1;
	int index_L_TOP = 0;

	//左上候補点
	for(int i = 0; i < N; i++){

		if(MAP[A[i]] > maximum){

			maximum = MAP[A[i]];
			L_TOP[index_L_TOP++] = i;
			is_L_TOP[i] = true;

		}else{

			is_L_TOP[i] = false;
		}
	}

	ll minimum = BIG_NUM;

	stack<int> tmp_R;
	//右下候補点
	for(int i = N-1; i >= 0; i--){

		if(MAP[A[i]] < minimum){
			minimum = MAP[A[i]];
			tmp_R.push(i);
			is_R_BOTTOM[i] = true;

		}else{

			is_R_BOTTOM[i] = false;
		}
	}
	while(!tmp_R.empty()){

		R_BOTTOM.push_back(tmp_R.top());
		tmp_R.pop();
	}

	int index_MID = 0;
	int left,right,mid;

	for(int i = 0; i < N; i++){

		if(is_L_TOP[i] || is_R_BOTTOM[i])continue;

		MID[index_MID] = i;

		/*自分より左上にある点の範囲を求める*/

		//右端
		left = 0,right = index_L_TOP-1,mid = (left+right)/2;
		R[index_MID] = -1;

		while(left <= right){

			if(L_TOP[mid] < i){

				R[index_MID] = mid;
				left = mid+1;

			}else{

				right = mid-1;
			}
			mid = (left+right)/2;
		}

		//左端
		left = 0,right = index_L_TOP-1,mid = (left+right)/2;
		L[index_MID] = N;

		while(left <= right){

			if(A[L_TOP[mid]] > A[i]){

				L[index_MID] = mid;
				right = mid-1;

			}else{

				left = mid+1;
			}
			mid = (left+right)/2;
		}

		//自分と同じ数の、L_TOPがあるか調べる
		left = 0,right = index_L_TOP-1,mid = (left+right)/2;
		SAME_L_TOP[index_MID] = -1;

		while(left <= right){

			if(A[L_TOP[mid]] > A[i]){

				right = mid-1;

			}else if(A[L_TOP[mid]] == A[i]){

				SAME_L_TOP[index_MID] = mid;
				break;

			}else{

				left = mid+1;
			}
			mid = (left+right)/2;
		}

		index_MID++;
	}

	init(N);

	for(ll i = 0; i <= 2*seg_N-2; i++){
		max_data[i] = 0;
		add_data[i] = 0;
	}

	ll max_contain = 0;
	int tmp_index = 0;

	priority_queue<Info> Q;

	int seg_L = 0,seg_R = index_L_TOP-1;

	for(int i = 0; i <= V.size(); i++){

		count_table[i] = 0; //数字の個数
	}

	ll pre_bottom = -1;
	vector<Info> work;

	for(int i = 0; i < R_BOTTOM.size(); i++){

		int r_bottom = R_BOTTOM[i];

		//自分未満になったMIDを出す
		while(Q.empty() == false && Q.top().value < A[r_bottom]){

			if(L[Q.top().mid_index] <= R[Q.top().mid_index]){

				if(A[MID[Q.top().mid_index]] != pre_bottom){

					add(L[Q.top().mid_index],R[Q.top().mid_index],-2,0,0,seg_N-1);

				}else{ //前回の下線に位置していた点の場合

					add(L[Q.top().mid_index],R[Q.top().mid_index],-1,0,0,seg_N-1);
				}
			}
			Q.pop();
		}

		//自分と同じ数があったら、2を加算しているので1を引く(左上とは交換する必要あるが右下とは不要なため)
		while(Q.empty() == false && Q.top().value == A[r_bottom]){

			add(L[Q.top().mid_index],R[Q.top().mid_index],-1,0,0,seg_N-1);
			work.push_back(Q.top());
			Q.pop();
		}
		for(int k = 0; k < work.size(); k++){

			Q.push(work[k]);
		}
		work.clear();

		//自分以上になったMIDを入れる
		while(tmp_index < index_MID && MID[tmp_index] < r_bottom){

			count_table[MAP[A[MID[tmp_index]]]]++;

			if(A[MID[tmp_index]] > A[r_bottom]){


				if(L[tmp_index] <= R[tmp_index]){

					add(L[tmp_index],R[tmp_index],2,0,0,seg_N-1);
				}
				if(SAME_L_TOP[tmp_index] != -1){ //自分より左に自分と同じ数があれば足す

					add(SAME_L_TOP[tmp_index],SAME_L_TOP[tmp_index],1,0,0,seg_N-1);
				}
				Q.push(Info(tmp_index,A[MID[tmp_index]]));

			}else if(A[MID[tmp_index]] == A[r_bottom]){ //下線と同じ高さ

				if(L[tmp_index] <= R[tmp_index]){

					add(L[tmp_index],R[tmp_index],1,0,0,seg_N-1);
				}
				Q.push(Info(tmp_index,A[MID[tmp_index]]));
			}
			tmp_index++;
		}


		//自分以下になった左上の点を抜く
		while(seg_L < index_L_TOP && A[L_TOP[seg_L]] <= A[r_bottom])seg_L++;

		if(seg_L <= seg_R){

			ll tmp_contain = getMax(seg_L,seg_R,0,0,seg_N-1)+1;
			max_contain = max(max_contain,tmp_contain);
		}

		pre_bottom = A[r_bottom];
	}

	printf("%lld\n",swap_count-max_contain);

	return 0;
}
accuracy: 1
time_ms: 200
memory_kb: 22648
final_rank: 7

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 100005


struct Info{
	Info(int arg_mid_index,ll arg_value){
		mid_index = arg_mid_index;
		value = arg_value;
	}
	bool operator<(const struct Info &arg) const{

		return value > arg.value; //値の昇順(PQ)
	}

	int mid_index;
	ll value;
};

ll N;
ll A[SIZE],BIT[SIZE];
ll L_TOP[SIZE],MID[SIZE];
ll L[SIZE],R[SIZE];
bool is_L_TOP[SIZE],is_R_BOTTOM[SIZE];
vector<ll> V,R_BOTTOM;
map<ll,ll> MAP;

ll max_data[8*SIZE],add_data[8*SIZE];
ll seg_N = 1;

void add(ll loc,ll value){

	BIT[loc] += value;

	loc += loc & -loc;

	while(loc <= N){
		BIT[loc] += value;
		loc += loc & -loc;
	}
}

ll getSum(ll loc){

	ll sum = BIT[loc];

	loc -= loc & -loc;

	while(loc > 0){
		sum += BIT[loc];
		loc -= loc & -loc;
	}
	return sum;
}

ll calc(ll left,ll right){
	return getSum(right)-getSum(left-1);
}


//RAQ and RMQ
void init(ll first_N){
	while(seg_N < first_N)seg_N *= 2;
}


void add(int left,int right,ll value,int node_id,int node_left,int node_right){

	if(right < node_left || left > node_right){
		//範囲外ならreturn
		return;
	}
	else if(left <= node_left && right >= node_right){ //このノードのカバーしている区間が、更新区間の部分区間である場合

		add_data[node_id] += value; //一様に加える値を加算

		while(node_id != 0){

			node_id = (node_id-1)/2;
			max_data[node_id] = max(max_data[2*node_id+1]+add_data[2*node_id+1],max_data[2*node_id+2]+add_data[2*node_id+2]);
		}
	}else{

		add(left,right,value,2*node_id+1,node_left,(node_left+node_right)/2);
		add(left,right,value,2*node_id+2,(node_left+node_right)/2+1,node_right);
	}
}

ll getMax(int left,int right,int node_id,int node_left,int node_right){
	if(right < node_left || left > node_right)return -BIG_NUM;
	else if(left <= node_left && right >= node_right){
		return max_data[node_id]+add_data[node_id];

	}else{

		ll  left_max  = getMax(left,right,2*node_id+1,node_left,(node_left+node_right)/2);
		ll  right_max = getMax(left,right,2*node_id+2,(node_left+node_right)/2+1,node_right);
		return max(left_max,right_max)+add_data[node_id];
	}
}


int main(){

	scanf("%d",&N);

	for(int i = 0; i < N; i++){

		scanf("%lld",&A[i]);
		V.push_back(A[i]);
	}

	sort(V.begin(),V.end());
	V.erase(unique(V.begin(),V.end()),V.end());

	for(int i = 0; i < V.size(); i++){

		MAP[V[i]] = i;
	}

	for(int i = 0; i <= V.size(); i++)BIT[i] = 0;

	ll swap_count = 0;

	for(ll i = 0; i < N; i++){
		swap_count += i-getSum(MAP[A[i]]+1);
		add(MAP[A[i]]+1,1);
	}

	if(swap_count == 0){

		for(int i = 1; i < N; i++){
			if(A[i-1] == A[i]){

				printf("0\n");
				return 0;
			}
		}

		printf("1\n");
		return 0;
	}

	ll maximum = -1;
	int index_L_TOP = 0;

	//左上候補点
	for(int i = 0; i < N; i++){

		if(MAP[A[i]] > maximum){

			maximum = MAP[A[i]];
			L_TOP[index_L_TOP++] = i;
			is_L_TOP[i] = true;

		}else{

			is_L_TOP[i] = false;
		}
	}

	ll minimum = BIG_NUM;

	stack<int> tmp_R;
	//右下候補点
	for(int i = N-1; i >= 0; i--){

		if(MAP[A[i]] < minimum){
			minimum = MAP[A[i]];
			tmp_R.push(i);
			is_R_BOTTOM[i] = true;

		}else{

			is_R_BOTTOM[i] = false;
		}
	}
	while(!tmp_R.empty()){

		R_BOTTOM.push_back(tmp_R.top());
		tmp_R.pop();
	}

	int index_MID = 0;
	int left,right,mid;

	for(int i = 0; i < N; i++){

		if(is_L_TOP[i] || is_R_BOTTOM[i])continue;

		MID[index_MID] = i;

		/*自分より左上にある点の範囲を求める*/

		//右端
		left = 0,right = index_L_TOP-1,mid = (left+right)/2;
		R[index_MID] = -1;

		while(left <= right){

			if(L_TOP[mid] < i){

				R[index_MID] = mid;
				left = mid+1;

			}else{

				right = mid-1;
			}
			mid = (left+right)/2;
		}

		//左端
		left = 0,right = index_L_TOP-1,mid = (left+right)/2;
		L[index_MID] = N;

		while(left <= right){

			if(A[L_TOP[mid]] > A[i]){

				L[index_MID] = mid;
				right = mid-1;

			}else{

				left = mid+1;
			}
			mid = (left+right)/2;
		}
		index_MID++;
	}

	init(N);

	for(ll i = 0; i <= 2*seg_N-2; i++){
		max_data[i] = 0;
		add_data[i] = 0;
	}

	ll max_contain = 0;
	int tmp_index = 0;

	priority_queue<Info> Q;

	for(int i = 0; i < R_BOTTOM.size(); i++){

		int r_bottom = R_BOTTOM[i];

		//自分より下になったMIDを出す
		while(Q.empty() == false && Q.top().value < A[r_bottom]){

			if(L[Q.top().mid_index] <= R[Q.top().mid_index]){

				add(L[Q.top().mid_index],R[Q.top().mid_index],-1,0,0,seg_N-1);
			}
			Q.pop();
		}
		//自分より上になったMIDを入れる
		while(tmp_index < index_MID && MID[tmp_index] < r_bottom){

			if(A[MID[tmp_index]] > A[r_bottom]){

				if(L[tmp_index] <= R[tmp_index]){

					add(L[tmp_index],R[tmp_index],1,0,0,seg_N-1);
				}
				Q.push(Info(tmp_index,A[MID[tmp_index]]));
			}
			tmp_index++;
		}

		max_contain = max(max_contain,getMax(0,seg_N-1,0,0,seg_N-1)); //最大含有区間を求める
	}

	printf("%lld\n",swap_count-(2*max_contain+1));

	return 0;
}
accuracy: 0.7476635514018691
time_ms: 160
memory_kb: 21044
final_rank: 16

code_snippet: #include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#define lol(i,n) for(int i=0;i<n;i++)
#define mod 1000000007
using namespace std;
typedef long long ll;
#define N (1<<17)
int n,m[N];
void Zaats(){
    vector<int> v;
    lol(i,n)v.push_back(m[i]);
    sort(v.begin(),v.end());
    lol(i,n){
	m[i]=lower_bound(v.begin(),v.end(),m[i])-v.begin();
    }
}
vector<int> A,B,Y;
void SetABY(){
    int maxi=-1;
    lol(i,n){
	if(maxi<m[i]){
	    maxi=m[i];
	    A.push_back(i);
	}
    }
    int mini=mod;
    for(int i=n-1;i>=0;i--){
	if(mini>m[i]){
	    mini=m[i];
	    B.push_back(i);
	}
    }
    sort(A.begin(),A.end());
    sort(B.begin(),B.end());
    vector<pair<int,int> >v;
    lol(i,n)v.push_back(make_pair(m[i],i));
    sort(v.begin(),v.end());
    lol(i,n)Y.push_back(v[i].second);
}
class RAQxRMQ{
private:
    ll dat[2*N],laz[2*N];
    void eval(int k){
	dat[k]+=laz[k];
	if(k<N-1){
	    laz[k*2+1]+=laz[k];
	    laz[k*2+2]+=laz[k];
	}
	laz[k]=0;
    }
    void ufs(int l,int r,int a,int b,int k,ll x){
	eval(k);
	if(l<=a&&b<=r){laz[k]+=x;eval(k);return;}
	if(b<=l||r<=a)return;
	ufs(l,r,a,(a+b)/2,k*2+1,x);
	ufs(l,r,(a+b)/2,b,k*2+2,x);
	dat[k]=max(dat[k*2+1],dat[k*2+2]);
    }
    ll dfs(int l,int r,int a,int b,int k){
	eval(k);
	if(l<=a&&b<=r)return dat[k];
	if(b<=l||r<=a)return 0;
	ll vl=dfs(l,r,a,(a+b)/2,k*2+1);
	ll vr=dfs(l,r,(a+b)/2,b,k*2+2);
	return max(vl,vr);
    }
public:
    void Init(){
	lol(i,2*N)dat[i]=laz[i]=0;
    }
    void Add(int l,int r,ll x){
	ufs(l,r+1,0,N,0,x);
    }
    ll Max(int l,int r){
	return dfs(l,r+1,0,N,0);
    }
};
class RSQ{
private:
    ll dat[2*N];
    ll dfs(int l,int r,int a,int b,int k){
	if(l<=a&&b<=r)return dat[k];
	if(b<=l||r<=a)return 0;
	ll vl=dfs(l,r,a,(a+b)/2,k*2+1);
	ll vr=dfs(l,r,(a+b)/2,b,k*2+2);
	return vl+vr;
    }
public:
    void Init(){
	lol(i,2*N)dat[i]=0;
    }
    void Upd(int i,int x){
	i+=N-1,dat[i]=x;
	while(i>0){
	    i=(i-1)/2;
	    dat[i]=dat[i*2+1]+dat[i*2+2];
	}
    }
    void Add(int i,int x){
	Upd(i,Sum(i,i)+x);
    }
    int Sum(int l,int r){
	return dfs(l,r+1,0,N,0);
    }
};
ll Tentou(){
    RSQ seg;seg.Init();
    ll res=0;
    lol(i,n){
	res+=seg.Sum(m[i]+1,n);
	seg.Add(m[i],1);
    }
    return res;
}
bool Topo(ll x1,ll y1,ll x2,ll y2){
    return (x1<x2&&y1>y2);
}
ll L,R;
void BNS(ll x,ll y){
    ll l,r,mid;
    l=-1,r=B.size();
    while(l<r-1){
	mid=(l+r)/2;
	if(B[mid]>x)r=mid;
	else l=mid;
    }
    L=r;
    l=-1,r=B.size();
    while(l<r-1){
	mid=(l+r)/2;
	if(m[B[mid]]<y)l=mid;
	else r=mid;
    }
    R=l;
}
int main(){
    cin>>n;
    lol(i,n)cin>>m[i];
    Zaats();
    SetABY();
    RAQxRMQ seg;seg.Init();
    ll ans=0,px=0,py1=0,py2=0,bx=-1,by=-1;
    lol(i,A.size()){
	ll ax=A[i],ay=m[A[i]];
	for(;px<n;px++){
	    ll x=px,y=m[px];
	    if(!(x<=ax))break;
	    if(Topo(bx,by,x,y)){
		BNS(x,y+1);
		seg.Add(L,R,-1);
	    }
	    if(Topo(bx,by+1,x,y)){
		BNS(x,y);
		seg.Add(L,R,-1);
	    }
	}
	for(;py1<n;py1++){
	    ll x=Y[py1],y=m[Y[py1]];
	    if(!(y<ay))break;
	    if(Topo(ax,ay,x,y)){
		BNS(x,y+1);
		seg.Add(L,R,1);
	    }
	}
	for(;py2<n;py2++){
	    ll x=Y[py2],y=m[Y[py2]];
	    if(!(y<=ay))break;
	    if(Topo(ax,ay+1,x,y)){
		BNS(x,y);
		seg.Add(L,R,1);
	    }
	}
	ans=max(ans,seg.Max(0,B.size()-1));
	bx=ax,by=ay;
    }
    ll t=Tentou();
    if(t==0){
	bool same=false;
	lol(i,n-1)if(m[Y[i]]==m[Y[i+1]])same=true;
	cout<<1-same<<endl;
    }
    else cout<<t-1-ans<<endl;
    return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 11176
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int64_t inf = 1001001001001001001ll;

template <typename T> class Compress {
private:
  size_t sz;
  std::vector<T> zip;
  std::vector<int> formatted;

public:
  Compress(std::vector<T> &v) : formatted(v.size(), -1), sz(v.size()) {
    zip = v;
    std::sort(zip.begin(), zip.end());
    zip.erase(std::unique(zip.begin(), zip.end()), zip.end());
    for (int i = 0; i < formatted.size(); ++i) {
      formatted[i] = std::lower_bound(zip.begin(), zip.end(), v[i]) - zip.begin();
    }
  }

  int operator[](size_t idx) {
    return formatted[idx];
  }

  T unzip(size_t idx) {
    assert(idx < zip.size());
    return zip[idx];
  }

  std::vector<int> get() {
    return formatted;
  }

  size_t size() {
    return sz;
  }
};

struct BinaryIndexedTree {
  BinaryIndexedTree(size_t n) : n(n), v(n + 1, 0) {}

  size_t n;
  vector<int64_t> v;

  int sum(int k) {
    int64_t ret = 0;
    for (; k; k -= k & -k) ret += v[k];
    return ret;
  }

  void add(int k, int x) {
    for (; k <= n; k += k & -k) v[k] += x;
  }
};

struct Node {
  int64_t node, lazy;
  Node() {}
  Node(int64_t node, int64_t lazy) : node(node), lazy(lazy) {}

  Node operator*(const Node &r) const {
    return Node(max(node, r.node), -inf);
  }
} e(0, -inf);

struct SegmentTree : Node {
  size_t n;
  vector<Node> seg;

  SegmentTree(size_t size) : n(1 << (32 - __builtin_clz(size - 1))), seg(2 * n - 1, e) {}

  inline void lazy_add(int k, int64_t x) {
    if (seg[k].lazy == -inf) {
      seg[k].lazy = 0;
    }
    seg[k].lazy += x;
  }

  inline void lazy_evaluate(int k) {
    if (seg[k].lazy != -inf) {
      seg[k].node += seg[k].lazy;
      if (k < n - 1) {
        lazy_add(2 * k + 1, seg[k].lazy);
        lazy_add(2 * k + 2, seg[k].lazy);
      }
      seg[k].lazy = -inf;
    }
  }

  inline void update_node(int k) {
    seg[k] = seg[2 * k + 1] * seg[2 * k + 2];
  }

  void add(int l, int r, int64_t x, int k, int a, int b) {
    lazy_evaluate(k);

    if (r <= a || b <= l) return;
    if (l <= a && b <= r) {
      lazy_add(k, x);
      lazy_evaluate(k);
      return;
    }

    add(l, r, x, 2 * k + 1, a, (a + b) / 2);
    add(l, r, x, 2 * k + 2, (a + b) / 2, b);
    update_node(k);
  }

  Node query(int l, int r, int k, int a, int b) {
    lazy_evaluate(k);
    if (r <= a || b <= l) return e;
    if (l <= a && b <= r) return seg[k];

    return query(l, r, 2 * k + 1, a, (a + b) / 2) * query(l, r, 2 * k + 2, (a + b) / 2, b);
  }

  void add(int l, int r, int64_t x) {
    // cerr << "range [" << l << ", " << r << ") add to " << x << endl;
    add(l, r, x, 0, 0, n);
  }

  int64_t query(int l, int r) {
    // cerr << "range [" << l << ", " << r << ") query of " << query(l, r, 0, 0, n).node << endl;
    return query(l, r, 0, 0, n).node;
  }

  void debug() {
    for (int i = 0; i < n; ++i) {
      cout << query(i, i + 1) << (i + 1 == n ? "\n" : " ");
    }
  }
};

signed main() {
  int n;
  cin >> n;

  vector<int> a(n);
  for (int i = 0; i < n; ++i) {
    cin >> a[i];
  }

  Compress<int> zip(a);
  a = zip.get();

  int64_t inversion = 0;
  BinaryIndexedTree bit(n + 1);
  for (int64_t i = 0; i < n; ++i) {
    inversion += i - bit.sum(a[i] + 1);
    bit.add(a[i] + 1, 1);
  }

  // cerr << "inversion : " << inversion << endl;

  if (inversion == 0) {
    a.erase(unique(a.begin(), a.end()), a.end());

    cout << (a.size() == n) << endl;
    return 0;
  }

  int seg_size = 0, max_a = -1, min_a = 1001001001;
  vector<int> val, idx, top(n), bottom(n);
  for (int i = 0; i < n; ++i) {
    if (max_a < a[i]) {
      val.push_back(a[i]);
      idx.push_back(i);
      top[i] = 1;
      max_a = a[i];
      seg_size++;
    }
  }
  for (int i = n - 1; i >= 0; --i) {
    if (min_a > a[i]) {
      bottom[i] = 1;
      min_a = a[i];
    }
  }

  int64_t ans = inf;
  SegmentTree seg(seg_size);
  priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
  for (int i = 0; i < n; ++i) {
    if (!bottom[i]) {
      // cerr << i << " is the other." << endl;
      if (*lower_bound(val.begin(), val.end(), a[i]) == a[i]) {
        int index = lower_bound(val.begin(), val.end(), a[i]) - val.begin();
        seg.add(index, index + 1, 1);
      }
      int l = lower_bound(val.begin(), val.end(), a[i] + 1) - val.begin();
      int r = lower_bound(idx.begin(), idx.end(), i) - idx.begin();
      seg.add(l, r, 2);
      pq.push(make_pair(a[i], i));
    }
    if (bottom[i]) {
      // cerr << i << " is bottom." << endl;
      queue<pair<int, int>> q;
      while (!pq.empty() && pq.top().first <= a[i]) {
        pair<int, int> p = pq.top();
        pq.pop();

        if (a[i] == p.first) {
          int l = lower_bound(val.begin(), val.end(), p.first + 1) - val.begin();
          int r = lower_bound(idx.begin(), idx.end(), p.second) - idx.begin();
          seg.add(l, r, -1);
          q.push(make_pair(l, r));
          continue;
        }

        if (*lower_bound(val.begin(), val.end(), p.first) == p.first) {
          int index = lower_bound(val.begin(), val.end(), p.first) - val.begin();
          seg.add(index, index + 1, -1);
        }
        int l = lower_bound(val.begin(), val.end(), p.first + 1) - val.begin();
        int r = lower_bound(idx.begin(), idx.end(), p.second) - idx.begin();
        seg.add(l, r, -2);
      }

      int l = lower_bound(val.begin(), val.end(), a[i]) - val.begin();
      int r = lower_bound(idx.begin(), idx.end(), i) - idx.begin();
      ans = min(ans, inversion - seg.query(l, r));

      while (!q.empty()) {
        seg.add(q.front().first, q.front().second, -1);
        q.pop();
      }
    }
    if (top[i]) {
      // cerr << i << " is top." << endl;
    }
  }

  cout << ans << endl;
}
accuracy: 1
time_ms: 90
memory_kb: 9408
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int64_t inf = 1001001001001001001ll;

template <typename T> class Compress {
private:
  size_t sz;
  std::vector<T> zip;
  std::vector<int> formatted;

public:
  Compress(std::vector<T> &v) : formatted(v.size(), -1), sz(v.size()) {
    zip = v;
    std::sort(zip.begin(), zip.end());
    zip.erase(std::unique(zip.begin(), zip.end()), zip.end());
    for (int i = 0; i < formatted.size(); ++i) {
      formatted[i] = std::lower_bound(zip.begin(), zip.end(), v[i]) - zip.begin();
    }
  }

  int operator[](size_t idx) {
    return formatted[idx];
  }

  T unzip(size_t idx) {
    assert(idx < zip.size());
    return zip[idx];
  }

  std::vector<int> get() {
    return formatted;
  }

  size_t size() {
    return sz;
  }
};

struct BinaryIndexedTree {
  BinaryIndexedTree(size_t n) : n(n), v(n + 1, 0) {}

  size_t n;
  vector<int64_t> v;

  int sum(int k) {
    int64_t ret = 0;
    for (; k; k -= k & -k) ret += v[k];
    return ret;
  }

  void add(int k, int x) {
    for (; k <= n; k += k & -k) v[k] += x;
  }
};

struct Node {
  int64_t node, lazy;
  Node() {}
  Node(int64_t node, int64_t lazy) : node(node), lazy(lazy) {}

  Node operator*(const Node &r) const {
    return Node(max(node, r.node), -inf);
  }
} e(0, -inf);

struct SegmentTree : Node {
  size_t n;
  vector<Node> seg;

  SegmentTree(size_t size) : n(1 << (32 - __builtin_clz(size - 1))), seg(2 * n - 1, e) {}

  inline void lazy_add(int k, int64_t x) {
    if (seg[k].lazy == -inf) {
      seg[k].lazy = 0;
    }
    seg[k].lazy += x;
  }

  inline void lazy_evaluate(int k) {
    if (seg[k].lazy != -inf) {
      seg[k].node += seg[k].lazy;
      if (k < n - 1) {
        lazy_add(2 * k + 1, seg[k].lazy);
        lazy_add(2 * k + 2, seg[k].lazy);
      }
      seg[k].lazy = -inf;
    }
  }

  inline void update_node(int k) {
    seg[k] = seg[2 * k + 1] * seg[2 * k + 2];
  }

  void add(int l, int r, int64_t x, int k, int a, int b) {
    lazy_evaluate(k);

    if (r <= a || b <= l) return;
    if (l <= a && b <= r) {
      lazy_add(k, x);
      lazy_evaluate(k);
      return;
    }

    add(l, r, x, 2 * k + 1, a, (a + b) / 2);
    add(l, r, x, 2 * k + 2, (a + b) / 2, b);
    update_node(k);
  }

  Node query(int l, int r, int k, int a, int b) {
    lazy_evaluate(k);
    if (r <= a || b <= l) return e;
    if (l <= a && b <= r) return seg[k];

    return query(l, r, 2 * k + 1, a, (a + b) / 2) * query(l, r, 2 * k + 2, (a + b) / 2, b);
  }

  void add(int l, int r, int64_t x) {
    // cerr << "range [" << l << ", " << r << ") add to " << x << endl;
    add(l, r, x, 0, 0, n);
  }

  int64_t query(int l, int r) {
    // cerr << "range [" << l << ", " << r << ") query of " << query(l, r, 0, 0, n).node << endl;
    return query(l, r, 0, 0, n).node;
  }

  void debug() {
    for (int i = 0; i < n; ++i) {
      cout << query(i, i + 1) << (i + 1 == n ? "\n" : " ");
    }
  }
};

signed main() {
  int n;
  cin >> n;

  vector<int> a(n);
  for (int i = 0; i < n; ++i) {
    cin >> a[i];
  }

  Compress<int> zip(a);
  a = zip.get();

  int64_t inversion = 0;
  BinaryIndexedTree bit(n + 1);
  for (int64_t i = 0; i < n; ++i) {
    inversion += i - bit.sum(a[i] + 1);
    bit.add(a[i] + 1, 1);
  }

  // cerr << "inversion : " << inversion << endl;

  if (inversion == 0) {
    if (*max_element(a.begin(), a.end())) {
      cout << 1 << endl;
    } else {
      cout << 0 << endl;
    }
    return 0;
  }

  int seg_size = 0, max_a = -1, min_a = 1001001001;
  vector<int> val, idx, top(n), bottom(n);
  for (int i = 0; i < n; ++i) {
    if (max_a < a[i]) {
      val.push_back(a[i]);
      idx.push_back(i);
      top[i] = 1;
      max_a = a[i];
      seg_size++;
    }
  }
  for (int i = n - 1; i >= 0; --i) {
    if (min_a > a[i]) {
      bottom[i] = 1;
      min_a = a[i];
    }
  }

  int64_t ans = inf;
  SegmentTree seg(seg_size);
  priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
  for (int i = 0; i < n; ++i) {
    if (!bottom[i]) {
      // cerr << i << " is the other." << endl;
      if (*lower_bound(val.begin(), val.end(), a[i]) == a[i]) {
        int index = lower_bound(val.begin(), val.end(), a[i]) - val.begin();
        seg.add(index, index + 1, 1);
      }
      int l = lower_bound(val.begin(), val.end(), a[i] + 1) - val.begin();
      int r = lower_bound(idx.begin(), idx.end(), i) - idx.begin();
      seg.add(l, r, 2);
      pq.push(make_pair(a[i], i));
    }
    if (bottom[i]) {
      // cerr << i << " is bottom." << endl;
      queue<pair<int, int>> q;
      while (!pq.empty() && pq.top().first <= a[i]) {
        pair<int, int> p = pq.top();
        pq.pop();

        if (a[i] == p.first) {
          int l = lower_bound(val.begin(), val.end(), p.first + 1) - val.begin();
          int r = lower_bound(idx.begin(), idx.end(), p.second) - idx.begin();
          seg.add(l, r, -1);
          q.push(make_pair(l, r));
          continue;
        }

        if (*lower_bound(val.begin(), val.end(), p.first) == p.first) {
          int index = lower_bound(val.begin(), val.end(), p.first) - val.begin();
          seg.add(index, index + 1, -1);
        }
        int l = lower_bound(val.begin(), val.end(), p.first + 1) - val.begin();
        int r = lower_bound(idx.begin(), idx.end(), p.second) - idx.begin();
        seg.add(l, r, -2);
      }

      int l = lower_bound(val.begin(), val.end(), a[i]) - val.begin();
      int r = lower_bound(idx.begin(), idx.end(), i) - idx.begin();
      ans = min(ans, inversion - seg.query(l, r));

      while (!q.empty()) {
        seg.add(q.front().first, q.front().second, -1);
        q.pop();
      }
    }
    if (top[i]) {
      // cerr << i << " is top." << endl;
    }
  }

  cout << ans << endl;
}
accuracy: 0.9813084112149533
time_ms: 90
memory_kb: 9460
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int64_t inf = 1001001001001001001ll;

template <typename T> class Compress {
private:
  size_t sz;
  std::vector<T> zip;
  std::vector<int> formatted;

public:
  Compress(std::vector<T> &v) : formatted(v.size(), -1), sz(v.size()) {
    zip = v;
    std::sort(zip.begin(), zip.end());
    zip.erase(std::unique(zip.begin(), zip.end()), zip.end());
    for (int i = 0; i < formatted.size(); ++i) {
      formatted[i] = std::lower_bound(zip.begin(), zip.end(), v[i]) - zip.begin();
    }
  }

  int operator[](size_t idx) {
    return formatted[idx];
  }

  T unzip(size_t idx) {
    assert(idx < zip.size());
    return zip[idx];
  }

  std::vector<int> get() {
    return formatted;
  }

  size_t size() {
    return sz;
  }
};

struct BinaryIndexedTree {
  BinaryIndexedTree(size_t n) : n(n), v(n + 1, 0) {}

  size_t n;
  vector<int64_t> v;

  int sum(int k) {
    int64_t ret = 0;
    for (; k; k -= k & -k) ret += v[k];
    return ret;
  }

  void add(int k, int x) {
    for (; k <= n; k += k & -k) v[k] += x;
  }
};

struct Node {
  int64_t node, lazy;
  Node() {}
  Node(int64_t node, int64_t lazy) : node(node), lazy(lazy) {}

  Node operator*(const Node &r) const {
    return Node(max(node, r.node), -inf);
  }
} e(0, -inf);

struct SegmentTree : Node {
  size_t n;
  vector<Node> seg;

  SegmentTree(size_t size) : n(1 << (32 - __builtin_clz(size - 1))), seg(2 * n - 1, e) {}

  inline void lazy_add(int k, int64_t x) {
    if (seg[k].lazy == -inf) {
      seg[k].lazy = 0;
    }
    seg[k].lazy += x;
  }

  inline void lazy_evaluate(int k) {
    if (seg[k].lazy != -inf) {
      seg[k].node += seg[k].lazy;
      if (k < n - 1) {
        lazy_add(2 * k + 1, seg[k].lazy);
        lazy_add(2 * k + 2, seg[k].lazy);
      }
      seg[k].lazy = -inf;
    }
  }

  inline void update_node(int k) {
    seg[k] = seg[2 * k + 1] * seg[2 * k + 2];
  }

  void add(int l, int r, int64_t x, int k, int a, int b) {
    lazy_evaluate(k);

    if (r <= a || b <= l) return;
    if (l <= a && b <= r) {
      lazy_add(k, x);
      lazy_evaluate(k);
      return;
    }

    add(l, r, x, 2 * k + 1, a, (a + b) / 2);
    add(l, r, x, 2 * k + 2, (a + b) / 2, b);
    update_node(k);
  }

  Node query(int l, int r, int k, int a, int b) {
    lazy_evaluate(k);
    if (r <= a || b <= l) return e;
    if (l <= a && b <= r) return seg[k];

    return query(l, r, 2 * k + 1, a, (a + b) / 2) * query(l, r, 2 * k + 2, (a + b) / 2, b);
  }

  void add(int l, int r, int64_t x) {
    // cerr << "range [" << l << ", " << r << ") add to " << x << endl;
    add(l, r, x, 0, 0, n);
  }

  int64_t query(int l, int r) {
    // cerr << "range [" << l << ", " << r << ") query of " << query(l, r, 0, 0, n).node << endl;
    return query(l, r, 0, 0, n).node;
  }

  void debug() {
    for (int i = 0; i < n; ++i) {
      cout << query(i, i + 1) << (i + 1 == n ? "\n" : " ");
    }
  }
};

signed main() {
  int n;
  cin >> n;

  vector<int> a(n);
  for (int i = 0; i < n; ++i) {
    cin >> a[i];
  }

  Compress<int> zip(a);
  a = zip.get();

  int64_t inversion = 0;
  BinaryIndexedTree bit(n + 1);
  for (int64_t i = 0; i < n; ++i) {
    inversion += i - bit.sum(a[i] + 1);
    bit.add(a[i] + 1, 1);
  }

  // cerr << "inversion : " << inversion << endl;

  if (inversion == 0) {
    cout << 1 << endl;
    return 0;
  }

  int seg_size = 0, max_a = -1, min_a = 1001001001;
  vector<int> val, idx, top(n), bottom(n);
  for (int i = 0; i < n; ++i) {
    if (max_a < a[i]) {
      val.push_back(a[i]);
      idx.push_back(i);
      top[i] = 1;
      max_a = a[i];
      seg_size++;
    }
  }
  for (int i = n - 1; i >= 0; --i) {
    if (min_a > a[i]) {
      bottom[i] = 1;
      min_a = a[i];
    }
  }

  int64_t ans = inf;
  SegmentTree seg(seg_size);
  priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
  for (int i = 0; i < n; ++i) {
    if (!bottom[i]) {
      // cerr << i << " is the other." << endl;
      if (*lower_bound(val.begin(), val.end(), a[i]) == a[i]) {
        int index = lower_bound(val.begin(), val.end(), a[i]) - val.begin();
        seg.add(index, index + 1, 1);
      }
      int l = lower_bound(val.begin(), val.end(), a[i] + 1) - val.begin();
      int r = lower_bound(idx.begin(), idx.end(), i) - idx.begin();
      seg.add(l, r, 2);
      pq.push(make_pair(a[i], i));
    }
    if (bottom[i]) {
      // cerr << i << " is bottom." << endl;
      queue<pair<int, int>> q;
      while (!pq.empty() && pq.top().first <= a[i]) {
        pair<int, int> p = pq.top();
        pq.pop();

        if (a[i] == p.first) {
          int l = lower_bound(val.begin(), val.end(), p.first + 1) - val.begin();
          int r = lower_bound(idx.begin(), idx.end(), p.second) - idx.begin();
          seg.add(l, r, -1);
          q.push(make_pair(l, r));
          continue;
        }

        if (*lower_bound(val.begin(), val.end(), p.first) == p.first) {
          int index = lower_bound(val.begin(), val.end(), p.first) - val.begin();
          seg.add(index, index + 1, -1);
        }
        int l = lower_bound(val.begin(), val.end(), p.first + 1) - val.begin();
        int r = lower_bound(idx.begin(), idx.end(), p.second) - idx.begin();
        seg.add(l, r, -2);
      }

      int l = lower_bound(val.begin(), val.end(), a[i]) - val.begin();
      int r = lower_bound(idx.begin(), idx.end(), i) - idx.begin();
      ans = min(ans, inversion - seg.query(l, r));

      while (!q.empty()) {
        seg.add(q.front().first, q.front().second, -1);
        q.pop();
      }
    }
    if (top[i]) {
      // cerr << i << " is top." << endl;
    }
  }

  cout << ans << endl;
}
accuracy: 0.9719626168224299
time_ms: 90
memory_kb: 9360
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int64_t inf = 1001001001001001001ll;

template <typename T> class Compress {
private:
  size_t sz;
  std::vector<T> zip;
  std::vector<int> formatted;

public:
  Compress(std::vector<T> &v) : formatted(v.size(), -1), sz(v.size()) {
    zip = v;
    std::sort(zip.begin(), zip.end());
    zip.erase(std::unique(zip.begin(), zip.end()), zip.end());
    for (int i = 0; i < formatted.size(); ++i) {
      formatted[i] = std::lower_bound(zip.begin(), zip.end(), v[i]) - zip.begin();
    }
  }

  int operator[](size_t idx) {
    return formatted[idx];
  }

  T unzip(size_t idx) {
    assert(idx < zip.size());
    return zip[idx];
  }

  std::vector<int> get() {
    return formatted;
  }

  size_t size() {
    return sz;
  }
};

struct BinaryIndexedTree {
  BinaryIndexedTree(size_t n) : n(n), v(n + 1, 0) {}

  size_t n;
  vector<int64_t> v;

  int sum(int k) {
    int64_t ret = 0;
    for (; k; k -= k & -k) ret += v[k];
    return ret;
  }

  void add(int k, int x) {
    for (; k <= n; k += k & -k) v[k] += x;
  }
};

struct Node {
  int64_t node, lazy;
  Node() {}
  Node(int64_t node, int64_t lazy) : node(node), lazy(lazy) {}

  Node operator*(const Node &r) const {
    return Node(max(node, r.node), -inf);
  }
} e(0, -inf);

struct SegmentTree : Node {
  size_t n;
  vector<Node> seg;

  SegmentTree(size_t size) : n(1 << (32 - __builtin_clz(size - 1))), seg(2 * n - 1, e) {}

  inline void lazy_add(int k, int64_t x) {
    if (seg[k].lazy == -inf) {
      seg[k].lazy = 0;
    }
    seg[k].lazy += x;
  }

  inline void lazy_evaluate(int k) {
    if (seg[k].lazy != -inf) {
      seg[k].node += seg[k].lazy;
      if (k < n - 1) {
        lazy_add(2 * k + 1, seg[k].lazy);
        lazy_add(2 * k + 2, seg[k].lazy);
      }
      seg[k].lazy = -inf;
    }
  }

  inline void update_node(int k) {
    seg[k] = seg[2 * k + 1] * seg[2 * k + 2];
  }

  void add(int l, int r, int64_t x, int k, int a, int b) {
    lazy_evaluate(k);

    if (r <= a || b <= l) return;
    if (l <= a && b <= r) {
      lazy_add(k, x);
      lazy_evaluate(k);
      return;
    }

    add(l, r, x, 2 * k + 1, a, (a + b) / 2);
    add(l, r, x, 2 * k + 2, (a + b) / 2, b);
    update_node(k);
  }

  Node query(int l, int r, int k, int a, int b) {
    lazy_evaluate(k);
    if (r <= a || b <= l) return e;
    if (l <= a && b <= r) return seg[k];

    return query(l, r, 2 * k + 1, a, (a + b) / 2) * query(l, r, 2 * k + 2, (a + b) / 2, b);
  }

  void add(int l, int r, int64_t x) {
    // cerr << "range [" << l << ", " << r << ") add to " << x << endl;
    add(l, r, x, 0, 0, n);
  }

  int64_t query(int l, int r) {
    // cerr << "range [" << l << ", " << r << ") query of " << query(l, r, 0, 0, n).node << endl;
    return query(l, r, 0, 0, n).node;
  }

  void debug() {
    for (int i = 0; i < n; ++i) {
      cout << query(i, i + 1) << (i + 1 == n ? "\n" : " ");
    }
  }
};

int main() {
  int n;
  cin >> n;

  vector<int> a(n);
  for (int i = 0; i < n; ++i) {
    cin >> a[i];
  }

  Compress<int> zip(a);
  a = zip.get();

  int64_t inversion = 0;
  BinaryIndexedTree bit(n);
  for (int64_t i = 0; i < n; ++i) {
    inversion += i - bit.sum(a[i]);
    bit.add(a[i] + 1, 1);
  }

  // cerr << "inversion : " << inversion << endl;

  if (inversion == 0) {
    cout << 1 << endl;
    return 0;
  }

  int seg_size = 0, max_a = -1, min_a = n + 1;
  vector<int> val, idx, top(n), bottom(n);
  for (int i = 0; i < n; ++i) {
    if (max_a < a[i]) {
      val.push_back(a[i]);
      idx.push_back(i);
      top[i] = 1;
      max_a = a[i];
      seg_size++;
    }
  }
  for (int i = n - 1; i >= 0; --i) {
    if (min_a > a[i]) {
      bottom[i] = 1;
      min_a = a[i];
    }
  }

  int64_t ans = inf;
  SegmentTree seg(seg_size);
  priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
  int l = 0, r = 0;
  for (int i = 0; i < n; ++i) {
    if (!top[i] && !bottom[i]) {
      // cerr << i << " is the other." << endl;
      if (*lower_bound(val.begin(), val.end(), a[i]) == a[i]) {
        int index = lower_bound(val.begin(), val.end(), a[i]) - val.begin();
        seg.add(index, index + 1, 1);
      }
      int addl = lower_bound(val.begin(), val.end(), a[i] + 1) - val.begin();
      int addr = lower_bound(idx.begin(), idx.end(), i) - idx.begin();
      seg.add(addl, addr, 2);
      pq.push(make_pair(a[i], i));
    }
    if (bottom[i]) {
      // cerr << i << " is bottom." << endl;
      while (!pq.empty() && pq.top().first <= a[i]) {
        pair<int, int> p = pq.top();
        pq.pop();

        if (*lower_bound(val.begin(), val.end(), p.first) == p.first) {
          int index = lower_bound(val.begin(), val.end(), p.first) - val.begin();
          seg.add(index, index + 1, -1);
        }
        int addl = lower_bound(val.begin(), val.end(), p.first + 1) - val.begin();
        int addr = lower_bound(idx.begin(), idx.end(), p.second) - idx.begin();
        seg.add(addl, addr, -2);
      }

      int l = lower_bound(val.begin(), val.end(), a[i]) - val.begin();
      int r = lower_bound(idx.begin(), idx.end(), i) - idx.begin();
      ans = min(ans, inversion - seg.query(l, r) - 1);
    }
    if (top[i]) {
      // cerr << i << " is top." << endl;
    }
  }

  cout << ans << endl;
}
accuracy: 0.7476635514018691
time_ms: 60
memory_kb: 8876
final_rank: 10

code_snippet: #include <iostream>
#include <algorithm>
#include <limits>
#include <vector>
#include <tuple>
using namespace std;

template<typename Type> class StarrySkyTree {
public:
	unsigned size_; std::vector<Type> dat1, dat2, dat;
	inline void update_(unsigned a, unsigned b, Type x, unsigned k, unsigned l, unsigned r) {
		if (r <= a || b <= l) return;
		if (a <= l && r <= b) {
			dat2[k] += x; return;
		}
		update_(a, b, x, (k << 1), l, (l + r) >> 1);
		update_(a, b, x, (k << 1) + 1, (l + r) >> 1, r);
		dat1[k] = std::max(dat1[k << 1] + dat2[k << 1], dat1[(k << 1) + 1] + dat2[(k << 1) + 1]);
	}
	inline Type query_(unsigned a, unsigned b, unsigned k, unsigned l, unsigned r) {
		if (r <= a || b <= l) return std::numeric_limits<Type>::min();
		if (a <= l && r <= b) return dat1[k] + dat2[k];
		Type lc = query_(a, b, (k << 1), l, (l + r) >> 1);
		Type rc = query_(a, b, (k << 1) + 1, (l + r) >> 1, r);
		return std::max(lc, rc) + dat2[k];
	}
	//StarrySkyTree() : size_(0), dat(std::vector<Type>()) {};
	StarrySkyTree(int size__) {
		for (size_ = 1; size_ < size__; ) size_ <<= 1;
		dat1.resize(size_ << 1, 0);
		dat2.resize(size_ << 1, 0);
		dat.resize(size_ << 1, 0);
	}
	template<class T>
	StarrySkyTree(T begin_, T end_) {
		unsigned n = (end_ - begin_);
		for (size_ = 1; size_ < n; size_ <<= 1); dat.resize(size_ << 1, std::numeric_limits<Type>::min());
		for (unsigned i = 0; i < n; i++) dat[i + size_] = *(begin_ + i);
		for (unsigned i = size_ - 1; i > 0; i--) dat[i] = std::max(dat[i << 1], dat[(i << 1) + 1]);
	}
	inline unsigned size() { return size_; }
	inline void add(unsigned i, Type x) {
		update_(i, i + 1, x, 1, 0, size_);
	}
	inline void add(unsigned l, unsigned r, Type x) {
		update_(l, r, x, 1, 0, size_);
	}
	inline Type query(unsigned l, unsigned r) {
		return query_(l, r, 1, 0, size_);
	}
};

long long bit[100009];
void add(int pos, int x) {
	pos++;
	while (pos <= 100008) { bit[pos] += x; pos += (pos&-pos); }
}
long long sum(int pos) {
	long long s = 0; pos++;
	while (pos >= 1) { s += bit[pos]; pos -= (pos&-pos); }
	return s;
}

long long n, a[100009], b[100009], px[100009], py[100009], qx[100009], qy[100009], cnt1, cnt2; bool used[100009];
vector<pair<int, int>> Z;
vector<tuple<int, int, int, int>>D;

void init() {
	n = 0;
	for (int i = 0; i < 100009; i++) {
		a[i] = 0; px[i] = 0; py[i] = 0; qx[i] = 0; qy[i] = 0; used[i] = false; bit[i] = 0;
	}
	cnt1 = 0; cnt2 = 0;
	Z.clear(); D.clear();
}
void random_generate() {
	n = 3;
	for (int i = 1; i <= n; i++) { a[i] = rand() % 5 + 1; b[i] = a[i]; }
}
long long solve_Jury() {
	int res = 100000000;
	for (int i = 1; i <= n; i++) {
		for (int j = i + 1; j <= n; j++) {
			swap(a[i], a[j]);
			int ct = 0;
			for (int k = 1; k <= n; k++) {
				for (int l = k + 1; l <= n; l++) {
					if (a[k] > a[l])ct++;
				}
			}
			res = min(res, ct);
			swap(a[i], a[j]);
		}
	}
	return res;
}
long long solve_Part() {
	for (int i = 1; i <= n; i++) { Z.push_back(make_pair(a[i], 0)); }
	sort(Z.begin(), Z.end());
	for (int i = 1; i <= n; i++) {
		a[i] = lower_bound(Z.begin(), Z.end(), make_pair((int)a[i], 0)) - Z.begin();
	}
	long long cnt = 0;
	for (int i = 1; i <= n; i++) {
		cnt += (sum(100007) - sum(a[i])); add(a[i], 1);
	}
	if (cnt == 0) {
		for (int i = 1; i <= n - 1; i++) { if (a[i] == a[i + 1]) return 0; }
		return 1;
	}
	int maxn = -1;
	for (int i = 1; i <= n; i++) {
		if (maxn < a[i]) { maxn = a[i]; px[cnt1] = i; py[cnt1] = a[i]; cnt1++; used[i] = true; }
	}
	maxn = 1000000;
	for (int i = n; i >= 1; i--) {
		if (maxn > a[i]) { maxn = a[i]; qx[cnt2] = i; qy[cnt2] = a[i]; cnt2++; used[i] = true; }
	}
	reverse(qx, qx + cnt2);
	reverse(qy, qy + cnt2);
	for (int i = 1; i <= n; i++) {
		if (used[i] == true) continue;
		int pos1 = lower_bound(py, py + cnt1, a[i]) - py;
		int pos5 = lower_bound(py, py + cnt1, a[i] + 1) - py;
		int pos2 = upper_bound(px, px + cnt1, i) - px; pos2--;
		int pos3 = lower_bound(qx, qx + cnt2, i) - qx;
		int pos4 = upper_bound(qy, qy + cnt2, a[i]) - qy; pos4--;
		int pos6 = lower_bound(qy, qy + cnt2, a[i]) - qy; pos6--;
		D.push_back(make_tuple(pos1, -1, pos3, pos6));
		D.push_back(make_tuple(pos5 - 1, 1, pos3, pos6));
		D.push_back(make_tuple(pos5, -2, pos3, pos6));
		D.push_back(make_tuple(pos2, 2, pos3, pos6));
		D.push_back(make_tuple(pos5, -1, pos6 + 1, pos4));
		D.push_back(make_tuple(pos2, 1, pos6 + 1, pos4));
	}
	sort(D.begin(), D.end());
	StarrySkyTree<long long> A(n + 2); long long ret = 0;
	for (int i = 0; i < D.size(); i++) {
		A.add(get<2>(D[i]), get<3>(D[i]) + 1, -1 * get<1>(D[i]));
		ret = max(ret, A.query(0, n + 1));
		//for (int j = 0; j <= n; j++) { cout << A.query(j, j + 1) << " "; }cout << endl;
	}
	return cnt - ret - 1LL;
}

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	//long long J1 = solve_Jury();
	long long J2 = solve_Part();
	/*int wacase = 0;
	for (int i = 1; i <= 1000; i++) {
		init();
		random_generate();
		long long J1 = solve_Jury();
		long long J2 = solve_Part();
		if (J1 != J2) {
			cout << "Case " << i << " [WA " << wacase + 1 << "] : Jury = " << J1 << " Part = " << J2 << endl;
			cout << n << endl;
			for (int i = 1; i <= n; i++) { if (i >= 2)cout << " "; cout << b[i]; }
			cout << endl << endl;
			wacase++;
		}
	}*/
	cout << J2 << endl;
	return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 21724
final_rank: 6

code_snippet: #include <iostream>
#include <algorithm>
#include <limits>
#include <vector>
#include <tuple>
using namespace std;

template<typename Type> class StarrySkyTree {
public:
	unsigned size_; std::vector<Type> dat1, dat2, dat;
	inline void update_(unsigned a, unsigned b, Type x, unsigned k, unsigned l, unsigned r) {
		if (r <= a || b <= l) return;
		if (a <= l && r <= b) {
			dat2[k] += x; return;
		}
		update_(a, b, x, (k << 1), l, (l + r) >> 1);
		update_(a, b, x, (k << 1) + 1, (l + r) >> 1, r);
		dat1[k] = std::max(dat1[k << 1] + dat2[k << 1], dat1[(k << 1) + 1] + dat2[(k << 1) + 1]);
	}
	inline Type query_(unsigned a, unsigned b, unsigned k, unsigned l, unsigned r) {
		if (r <= a || b <= l) return std::numeric_limits<Type>::min();
		if (a <= l && r <= b) return dat1[k] + dat2[k];
		Type lc = query_(a, b, (k << 1), l, (l + r) >> 1);
		Type rc = query_(a, b, (k << 1) + 1, (l + r) >> 1, r);
		return std::max(lc, rc) + dat2[k];
	}
	//StarrySkyTree() : size_(0), dat(std::vector<Type>()) {};
	StarrySkyTree(int size__) {
		for (size_ = 1; size_ < size__; ) size_ <<= 1;
		dat1.resize(size_ << 1, 0);
		dat2.resize(size_ << 1, 0);
		dat.resize(size_ << 1, 0);
	}
	template<class T>
	StarrySkyTree(T begin_, T end_) {
		unsigned n = (end_ - begin_);
		for (size_ = 1; size_ < n; size_ <<= 1); dat.resize(size_ << 1, std::numeric_limits<Type>::min());
		for (unsigned i = 0; i < n; i++) dat[i + size_] = *(begin_ + i);
		for (unsigned i = size_ - 1; i > 0; i--) dat[i] = std::max(dat[i << 1], dat[(i << 1) + 1]);
	}
	inline unsigned size() { return size_; }
	inline void add(unsigned i, Type x) {
		update_(i, i + 1, x, 1, 0, size_);
	}
	inline void add(unsigned l, unsigned r, Type x) {
		update_(l, r, x, 1, 0, size_);
	}
	inline Type query(unsigned l, unsigned r) {
		return query_(l, r, 1, 0, size_);
	}
};

long long bit[100009];
void add(int pos, int x) {
	pos++;
	while (pos <= 100008) { bit[pos] += x; pos += (pos&-pos); }
}
long long sum(int pos) {
	long long s = 0; pos++;
	while (pos >= 1) { s += bit[pos]; pos -= (pos&-pos); }
	return s;
}

long long n, a[100009], b[100009], px[100009], py[100009], qx[100009], qy[100009], cnt1, cnt2; bool used[100009];
vector<pair<int, int>> Z;
vector<tuple<int, int, int, int>>D;

void init() {
	n = 0;
	for (int i = 0; i < 100009; i++) {
		a[i] = 0; px[i] = 0; py[i] = 0; qx[i] = 0; qy[i] = 0; used[i] = false; bit[i] = 0;
	}
	cnt1 = 0; cnt2 = 0;
	Z.clear(); D.clear();
}
void random_generate() {
	n = 3;
	for (int i = 1; i <= n; i++) { a[i] = rand() % 5 + 1; b[i] = a[i]; }
}
long long solve_Jury() {
	int res = 100000000;
	for (int i = 1; i <= n; i++) {
		for (int j = i + 1; j <= n; j++) {
			swap(a[i], a[j]);
			int ct = 0;
			for (int k = 1; k <= n; k++) {
				for (int l = k + 1; l <= n; l++) {
					if (a[k] > a[l])ct++;
				}
			}
			res = min(res, ct);
			swap(a[i], a[j]);
		}
	}
	return res;
}
long long solve_Part() {
	for (int i = 1; i <= n; i++) { Z.push_back(make_pair(a[i], 0)); }
	sort(Z.begin(), Z.end());
	for (int i = 1; i <= n; i++) {
		a[i] = lower_bound(Z.begin(), Z.end(), make_pair((int)a[i], 0)) - Z.begin();
	}
	long long cnt = 0;
	for (int i = 1; i <= n; i++) {
		cnt += (sum(100007) - sum(a[i])); add(a[i], 1);
	}
	if (cnt == 0) { return 1; }
	int maxn = -1;
	for (int i = 1; i <= n; i++) {
		if (maxn < a[i]) { maxn = a[i]; px[cnt1] = i; py[cnt1] = a[i]; cnt1++; used[i] = true; }
	}
	maxn = 1000000;
	for (int i = n; i >= 1; i--) {
		if (maxn > a[i]) { maxn = a[i]; qx[cnt2] = i; qy[cnt2] = a[i]; cnt2++; used[i] = true; }
	}
	reverse(qx, qx + cnt2);
	reverse(qy, qy + cnt2);
	for (int i = 1; i <= n; i++) {
		int P = 2; if (used[i] == true) continue;
		int pos1 = lower_bound(py, py + cnt1, a[i]) - py;
		int pos2 = upper_bound(px, px + cnt1, i) - px; pos2--;
		int pos3 = lower_bound(qx, qx + cnt2, i) - qx;
		int pos4 = upper_bound(qy, qy + cnt2, a[i]) - qy; pos4--;
		D.push_back(make_tuple(pos1, -P, pos3, pos4));
		D.push_back(make_tuple(pos2, P, pos3, pos4));
	}
	sort(D.begin(), D.end());
	StarrySkyTree<long long> A(n + 2); long long ret = 0;
	for (int i = 0; i < D.size(); i++) {
		A.add(get<2>(D[i]), get<3>(D[i]) + 1, -1 * get<1>(D[i]));
		ret = max(ret, A.query(0, n + 1));
		//for (int j = 0; j <= n; j++) { cout << A.query(j, j + 1) << " "; }cout << endl;
	}
	return cnt - ret - 1LL;
}

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	//long long J1 = solve_Jury();
	long long J2 = solve_Part();
	/*int wacase = 0;
	for (int i = 1; i <= 1000; i++) {
		init();
		random_generate();
		long long J1 = solve_Jury();
		long long J2 = solve_Part();
		if (J1 != J2) {
			cout << "Case " << i << " [WA " << wacase + 1 << "] : Jury = " << J1 << " Part = " << J2 << endl;
			cout << n << endl;
			for (int i = 1; i <= n; i++) { if (i >= 2)cout << " "; cout << b[i]; }
			cout << endl << endl;
			wacase++;
		}
	}*/
	cout << J2 << endl;
	return 0;
}
accuracy: 0.7476635514018691
time_ms: 90
memory_kb: 14552
final_rank: 14

code_snippet: #include <iostream>
#include <algorithm>
#include <limits>
#include <vector>
#include <tuple>
using namespace std;

template<typename Type> class StarrySkyTree {
public:
	unsigned size_; std::vector<Type> dat1, dat2, dat;
	inline void update_(unsigned a, unsigned b, Type x, unsigned k, unsigned l, unsigned r) {
		if (r <= a || b <= l) return;
		if (a <= l && r <= b) {
			dat2[k] += x; return;
		}
		update_(a, b, x, (k << 1), l, (l + r) >> 1);
		update_(a, b, x, (k << 1) + 1, (l + r) >> 1, r);
		dat1[k] = std::max(dat1[k << 1] + dat2[k << 1], dat1[(k << 1) + 1] + dat2[(k << 1) + 1]);
	}
	inline Type query_(unsigned a, unsigned b, unsigned k, unsigned l, unsigned r) {
		if (r <= a || b <= l) return std::numeric_limits<Type>::min();
		if (a <= l && r <= b) return dat1[k] + dat2[k];
		Type lc = query_(a, b, (k << 1), l, (l + r) >> 1);
		Type rc = query_(a, b, (k << 1) + 1, (l + r) >> 1, r);
		return std::max(lc, rc) + dat2[k];
	}
	//StarrySkyTree() : size_(0), dat(std::vector<Type>()) {};
	StarrySkyTree(int size__) {
		for (size_ = 1; size_ < size__; ) size_ <<= 1;
		dat1.resize(size_ << 1, 0);
		dat2.resize(size_ << 1, 0);
		dat.resize(size_ << 1, 0);
	}
	template<class T>
	StarrySkyTree(T begin_, T end_) {
		unsigned n = (end_ - begin_);
		for (size_ = 1; size_ < n; size_ <<= 1); dat.resize(size_ << 1, std::numeric_limits<Type>::min());
		for (unsigned i = 0; i < n; i++) dat[i + size_] = *(begin_ + i);
		for (unsigned i = size_ - 1; i > 0; i--) dat[i] = std::max(dat[i << 1], dat[(i << 1) + 1]);
	}
	inline unsigned size() { return size_; }
	inline void add(unsigned i, Type x) {
		update_(i, i + 1, x, 1, 0, size_);
	}
	inline void add(unsigned l, unsigned r, Type x) {
		update_(l, r, x, 1, 0, size_);
	}
	inline Type query(unsigned l, unsigned r) {
		return query_(l, r, 1, 0, size_);
	}
};

long long bit[100009];
void add(int pos, int x) {
	pos++;
	while (pos <= 100008) { bit[pos] += x; pos += (pos&-pos); }
}
long long sum(int pos) {
	long long s = 0;
	while (pos >= 1) { s += bit[pos]; pos -= (pos&-pos); }
	return s;
}

long long n, a[100009], b[100009], px[100009], py[100009], qx[100009], qy[100009], cnt1, cnt2; bool used[100009];
vector<pair<int, int>> Z;
vector<tuple<int, int, int, int>>D;

void init() {
	n = 0;
	for (int i = 0; i < 100009; i++) {
		a[i] = 0; px[i] = 0; py[i] = 0; qx[i] = 0; qy[i] = 0; used[i] = false; bit[i] = 0;
	}
	cnt1 = 0; cnt2 = 0;
	Z.clear(); D.clear();
}
void random_generate() {
	n = 5;
	while (true) {
		for (int i = 1; i <= n; i++) { a[i] = rand() % 20 + 1; b[i] = a[i]; }
		bool OK = false;
		for (int i = 1; i <= n; i++) {
			for (int j = i + 1; j <= n; j++) { if (a[i] == a[j])OK = true; }
		}
		if (OK == false) break;
	}
}
long long solve_Jury() {
	int res = 100000000;
	for (int i = 1; i <= n; i++) {
		for (int j = i + 1; j <= n; j++) {
			swap(a[i], a[j]);
			int ct = 0;
			for (int k = 1; k <= n; k++) {
				for (int l = k + 1; l <= n; l++) {
					if (a[k] > a[l])ct++;
				}
			}
			res = min(res, ct);
			swap(a[i], a[j]);
		}
	}
	return res;
}
long long solve_Part() {
	for (int i = 1; i <= n; i++) { Z.push_back(make_pair(a[i], 0)); }
	sort(Z.begin(), Z.end());
	for (int i = 1; i <= n; i++) {
		a[i] = lower_bound(Z.begin(), Z.end(), make_pair((int)a[i], 0)) - Z.begin();
	}
	long long cnt = 0;
	for (int i = 1; i <= n; i++) {
		cnt += (sum(100007) - sum(a[i])); add(a[i], 1);
	}
	if (cnt == 0) { return 1; }
	int maxn = -1;
	for (int i = 1; i <= n; i++) {
		if (maxn < a[i]) { maxn = a[i]; px[cnt1] = i; py[cnt1] = a[i]; cnt1++; used[i] = true; }
	}
	maxn = 1000000;
	for (int i = n; i >= 1; i--) {
		if (maxn > a[i]) { maxn = a[i]; qx[cnt2] = i; qy[cnt2] = a[i]; cnt2++; used[i] = true; }
	}
	reverse(qx, qx + cnt2);
	reverse(qy, qy + cnt2);
	for (int i = 1; i <= n; i++) {
		int P = 2; if (used[i] == true) continue;
		int pos1 = lower_bound(py, py + cnt1, a[i]) - py;
		int pos2 = upper_bound(px, px + cnt1, i) - px; pos2--;
		int pos3 = lower_bound(qx, qx + cnt2, i) - qx;
		int pos4 = upper_bound(qy, qy + cnt2, a[i]) - qy; pos4--;
		D.push_back(make_tuple(pos1, -P, pos3, pos4));
		D.push_back(make_tuple(pos2, P, pos3, pos4));
	}
	sort(D.begin(), D.end());
	StarrySkyTree<long long> A(n + 2); long long ret = 0;
	for (int i = 0; i < D.size(); i++) {
		A.add(get<2>(D[i]), get<3>(D[i]) + 1, -1 * get<1>(D[i]));
		ret = max(ret, A.query(0, n + 1));
		//for (int j = 0; j <= n; j++) { cout << A.query(j, j + 1) << " "; }cout << endl;
	}
	return cnt - ret - 1LL;
}

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	//long long J1 = solve_Jury();
	long long J2 = solve_Part();
	/*int wacase = 0;
	for (int i = 1; i <= 1000; i++) {
		init();
		random_generate();
		long long J1 = solve_Jury();
		long long J2 = solve_Part();
		if (J1 != J2) {
			cout << "Case " << i << " [WA " << wacase + 1 << "] : Jury = " << J1 << " Part = " << J2 << endl;
			cout << n << endl;
			for (int i = 1; i <= n; i++) { if (i >= 2)cout << " "; cout << b[i]; }
			cout << endl << endl;
			wacase++;
		}
	}*/
	cout << J2 << endl;
	return 0;
}
accuracy: 0.7476635514018691
time_ms: 90
memory_kb: 14404
final_rank: 13

code_snippet: #include <iostream>
#include <algorithm>
#include <limits>
#include <vector>
#include <tuple>
using namespace std;

template<typename Type> class StarrySkyTree {
public:
	unsigned size_; std::vector<Type> dat1, dat2, dat;
	inline void update_(unsigned a, unsigned b, Type x, unsigned k, unsigned l, unsigned r) {
		if (r <= a || b <= l) return;
		if (a <= l && r <= b) {
			dat2[k] += x; return;
		}
		update_(a, b, x, (k << 1), l, (l + r) >> 1);
		update_(a, b, x, (k << 1) + 1, (l + r) >> 1, r);
		dat1[k] = std::max(dat1[k << 1] + dat2[k << 1], dat1[(k << 1) + 1] + dat2[(k << 1) + 1]);
	}
	inline Type query_(unsigned a, unsigned b, unsigned k, unsigned l, unsigned r) {
		if (r <= a || b <= l) return std::numeric_limits<Type>::min();
		if (a <= l && r <= b) return dat1[k] + dat2[k];
		Type lc = query_(a, b, (k << 1), l, (l + r) >> 1);
		Type rc = query_(a, b, (k << 1) + 1, (l + r) >> 1, r);
		return std::max(lc, rc) + dat2[k];
	}
	//StarrySkyTree() : size_(0), dat(std::vector<Type>()) {};
	StarrySkyTree(int size__) {
		for (size_ = 1; size_ < size__; ) size_ <<= 1;
		dat1.resize(size_ << 1, 0);
		dat2.resize(size_ << 1, 0);
		dat.resize(size_ << 1, 0);
	}
	template<class T>
	StarrySkyTree(T begin_, T end_) {
		unsigned n = (end_ - begin_);
		for (size_ = 1; size_ < n; size_ <<= 1); dat.resize(size_ << 1, std::numeric_limits<Type>::min());
		for (unsigned i = 0; i < n; i++) dat[i + size_] = *(begin_ + i);
		for (unsigned i = size_ - 1; i > 0; i--) dat[i] = std::max(dat[i << 1], dat[(i << 1) + 1]);
	}
	inline unsigned size() { return size_; }
	inline void add(unsigned i, Type x) {
		update_(i, i + 1, x, 1, 0, size_);
	}
	inline void add(unsigned l, unsigned r, Type x) {
		update_(l, r, x, 1, 0, size_);
	}
	inline Type query(unsigned l, unsigned r) {
		return query_(l, r, 1, 0, size_);
	}
};

long long bit[100009];
void add(int pos, int x) {
	pos++;
	while (pos <= 100008) { bit[pos] += x; pos += (pos&-pos); }
}
long long sum(int pos) {
	long long s = 0;
	while (pos >= 1) { s += bit[pos]; pos -= (pos&-pos); }
	return s;
}

long long n, a[100009], b[100009], px[100009], py[100009], qx[100009], qy[100009], cnt1, cnt2; bool used[100009];
vector<pair<int, int>> Z;
vector<tuple<int, int, int, int>>D;

void init() {
	n = 0;
	for (int i = 0; i < 100009; i++) {
		a[i] = 0; px[i] = 0; py[i] = 0; qx[i] = 0; qy[i] = 0; used[i] = false; bit[i] = 0;
	}
	cnt1 = 0; cnt2 = 0;
	Z.clear(); D.clear();
}
void random_generate() {
	n = 5;
	while (true) {
		for (int i = 1; i <= n; i++) { a[i] = rand() % 20 + 1; b[i] = a[i]; }
		bool OK = false;
		for (int i = 1; i <= n; i++) {
			for (int j = i + 1; j <= n; j++) { if (a[i] == a[j])OK = true; }
		}
		if (OK == false) break;
	}
}
long long solve_Jury() {
	int res = 100000000;
	for (int i = 1; i <= n; i++) {
		for (int j = i + 1; j <= n; j++) {
			swap(a[i], a[j]);
			int ct = 0;
			for (int k = 1; k <= n; k++) {
				for (int l = k + 1; l <= n; l++) {
					if (a[k] > a[l])ct++;
				}
			}
			res = min(res, ct);
			swap(a[i], a[j]);
		}
	}
	return res;
}
long long solve_Part() {
	for (int i = 1; i <= n; i++) { Z.push_back(make_pair(a[i], -i)); }
	sort(Z.begin(), Z.end());
	for (int i = 1; i <= n; i++) {
		a[i] = lower_bound(Z.begin(), Z.end(), make_pair((int)a[i], -i)) - Z.begin();
	}
	long long cnt = 0;
	for (int i = 1; i <= n; i++) {
		cnt += (sum(100007) - sum(a[i])); add(a[i], 1);
	}
	if (cnt == 0) { return 1; }
	int maxn = -1;
	for (int i = 1; i <= n; i++) {
		if (maxn < a[i]) { maxn = a[i]; px[cnt1] = i; py[cnt1] = a[i]; cnt1++; used[i] = true; }
	}
	maxn = 1000000;
	for (int i = n; i >= 1; i--) {
		if (maxn > a[i]) { maxn = a[i]; qx[cnt2] = i; qy[cnt2] = a[i]; cnt2++; used[i] = true; }
	}
	reverse(qx, qx + cnt2);
	reverse(qy, qy + cnt2);
	for (int i = 1; i <= n; i++) {
		int P = 2; if (used[i] == true) continue;
		int pos1 = lower_bound(py, py + cnt1, a[i]) - py;
		int pos2 = upper_bound(px, px + cnt1, i) - px; pos2--;
		int pos3 = lower_bound(qx, qx + cnt2, i) - qx;
		int pos4 = upper_bound(qy, qy + cnt2, a[i]) - qy; pos4--;
		D.push_back(make_tuple(pos1, -P, pos3, pos4));
		D.push_back(make_tuple(pos2, P, pos3, pos4));
	}
	sort(D.begin(), D.end());
	StarrySkyTree<long long> A(n + 2); long long ret = 0;
	for (int i = 0; i < D.size(); i++) {
		A.add(get<2>(D[i]), get<3>(D[i]) + 1, -1 * get<1>(D[i]));
		ret = max(ret, A.query(0, n + 1));
		//for (int j = 0; j <= n; j++) { cout << A.query(j, j + 1) << " "; }cout << endl;
	}
	return cnt - ret - 1LL;
}

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	//long long J1 = solve_Jury();
	long long J2 = solve_Part();
	/*int wacase = 0;
	for (int i = 1; i <= 1000; i++) {
		init();
		random_generate();
		long long J1 = solve_Jury();
		long long J2 = solve_Part();
		if (J1 != J2) {
			cout << "Case " << i << " [WA " << wacase + 1 << "] : Jury = " << J1 << " Part = " << J2 << endl;
			cout << n << endl;
			for (int i = 1; i <= n; i++) { if (i >= 2)cout << " "; cout << b[i]; }
			cout << endl << endl;
			wacase++;
		}
	}*/
	cout << J2 << endl;
	return 0;
}
accuracy: 0.7476635514018691
time_ms: 80
memory_kb: 14444
final_rank: 11

code_snippet: #include <iostream>
#include <algorithm>
#include <limits>
#include <vector>
#include <tuple>
using namespace std;

template<typename Type> class StarrySkyTree {
public:
	unsigned size_; std::vector<Type> dat1, dat2, dat;
	inline void update_(unsigned a, unsigned b, Type x, unsigned k, unsigned l, unsigned r) {
		if (r <= a || b <= l) return;
		if (a <= l && r <= b) {
			dat2[k] += x; return;
		}
		update_(a, b, x, (k << 1), l, (l + r) >> 1);
		update_(a, b, x, (k << 1) + 1, (l + r) >> 1, r);
		dat1[k] = std::max(dat1[k << 1] + dat2[k << 1], dat1[(k << 1) + 1] + dat2[(k << 1) + 1]);
	}
	inline Type query_(unsigned a, unsigned b, unsigned k, unsigned l, unsigned r) {
		if (r <= a || b <= l) return std::numeric_limits<Type>::min();
		if (a <= l && r <= b) return dat1[k] + dat2[k];
		Type lc = query_(a, b, (k << 1), l, (l + r) >> 1);
		Type rc = query_(a, b, (k << 1) + 1, (l + r) >> 1, r);
		return std::max(lc, rc) + dat2[k];
	}
	//StarrySkyTree() : size_(0), dat(std::vector<Type>()) {};
	StarrySkyTree(int size__) {
		for (size_ = 1; size_ < size__; ) size_ <<= 1;
		dat1.resize(size_ << 1, 0);
		dat2.resize(size_ << 1, 0);
		dat.resize(size_ << 1, 0);
	}
	template<class T>
	StarrySkyTree(T begin_, T end_) {
		unsigned n = (end_ - begin_);
		for (size_ = 1; size_ < n; size_ <<= 1); dat.resize(size_ << 1, std::numeric_limits<Type>::min());
		for (unsigned i = 0; i < n; i++) dat[i + size_] = *(begin_ + i);
		for (unsigned i = size_ - 1; i > 0; i--) dat[i] = std::max(dat[i << 1], dat[(i << 1) + 1]);
	}
	inline unsigned size() { return size_; }
	inline void add(unsigned i, Type x) {
		update_(i, i + 1, x, 1, 0, size_);
	}
	inline void add(unsigned l, unsigned r, Type x) {
		update_(l, r, x, 1, 0, size_);
	}
	inline Type query(unsigned l, unsigned r) {
		return query_(l, r, 1, 0, size_);
	}
};

long long bit[100009];
void add(int pos, int x) {
	pos++;
	while (pos <= 100008) { bit[pos] += x; pos += (pos&-pos); }
}
long long sum(int pos) {
	long long s = 0;
	while (pos >= 1) { s += bit[pos]; pos -= (pos&-pos); }
	return s;
}

long long n, a[100009], b[100009], px[100009], py[100009], qx[100009], qy[100009], cnt1, cnt2; bool used[100009];
vector<pair<int, int>> Z;
vector<tuple<int, int, int, int>>D;

void init() {
	n = 0;
	for (int i = 0; i < 100009; i++) {
		a[i] = 0; px[i] = 0; py[i] = 0; qx[i] = 0; qy[i] = 0; used[i] = false; bit[i] = 0;
	}
	cnt1 = 0; cnt2 = 0;
	Z.clear(); D.clear();
}
void random_generate() {
	n = 5;
	while (true) {
		for (int i = 1; i <= n; i++) { a[i] = rand() % 20 + 1; b[i] = a[i]; }
		bool OK = false;
		for (int i = 1; i <= n; i++) {
			for (int j = i + 1; j <= n; j++) { if (a[i] == a[j])OK = true; }
		}
		if (OK == false) break;
	}
}
long long solve_Jury() {
	int res = 100000000;
	for (int i = 1; i <= n; i++) {
		for (int j = i + 1; j <= n; j++) {
			swap(a[i], a[j]);
			int ct = 0;
			for (int k = 1; k <= n; k++) {
				for (int l = k + 1; l <= n; l++) {
					if (a[k] > a[l])ct++;
				}
			}
			res = min(res, ct);
			swap(a[i], a[j]);
		}
	}
	return res;
}
long long solve_Part() {
	for (int i = 1; i <= n; i++) { Z.push_back(make_pair(a[i], i)); }
	sort(Z.begin(), Z.end());
	for (int i = 1; i <= n; i++) {
		a[i] = lower_bound(Z.begin(), Z.end(), make_pair((int)a[i], i)) - Z.begin();
	}
	long long cnt = 0;
	for (int i = 1; i <= n; i++) {
		cnt += (sum(100007) - sum(a[i])); add(a[i], 1);
	}
	if (cnt == 0) { return 1; }
	int maxn = -1;
	for (int i = 1; i <= n; i++) {
		if (maxn < a[i]) { maxn = a[i]; px[cnt1] = i; py[cnt1] = a[i]; cnt1++; used[i] = true; }
	}
	maxn = 1000000;
	for (int i = n; i >= 1; i--) {
		if (maxn > a[i]) { maxn = a[i]; qx[cnt2] = i; qy[cnt2] = a[i]; cnt2++; used[i] = true; }
	}
	reverse(qx, qx + cnt2);
	reverse(qy, qy + cnt2);
	for (int i = 1; i <= n; i++) {
		int P = 2; if (used[i] == true) continue;
		int pos1 = lower_bound(py, py + cnt1, a[i]) - py;
		int pos2 = upper_bound(px, px + cnt1, i) - px; pos2--;
		int pos3 = lower_bound(qx, qx + cnt2, i) - qx;
		int pos4 = upper_bound(qy, qy + cnt2, a[i]) - qy; pos4--;
		D.push_back(make_tuple(pos1, -P, pos3, pos4));
		D.push_back(make_tuple(pos2, P, pos3, pos4));
	}
	sort(D.begin(), D.end());
	StarrySkyTree<long long> A(n + 2); long long ret = 0;
	for (int i = 0; i < D.size(); i++) {
		A.add(get<2>(D[i]), get<3>(D[i]) + 1, -1 * get<1>(D[i]));
		ret = max(ret, A.query(0, n + 1));
		//for (int j = 0; j <= n; j++) { cout << A.query(j, j + 1) << " "; }cout << endl;
	}
	return cnt - ret - 1LL;
}

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	//long long J1 = solve_Jury();
	long long J2 = solve_Part();
	/*int wacase = 0;
	for (int i = 1; i <= 1000; i++) {
		init();
		random_generate();
		long long J1 = solve_Jury();
		long long J2 = solve_Part();
		if (J1 != J2) {
			cout << "Case " << i << " [WA " << wacase + 1 << "] : Jury = " << J1 << " Part = " << J2 << endl;
			cout << n << endl;
			for (int i = 1; i <= n; i++) { if (i >= 2)cout << " "; cout << b[i]; }
			cout << endl << endl;
			wacase++;
		}
	}*/
	cout << J2 << endl;
	return 0;
}
accuracy: 0.7476635514018691
time_ms: 80
memory_kb: 14504
final_rank: 12

code_snippet: #include <bits/stdc++.h>
#define int long long
#define mp make_pair
#define INF 2e+9
using namespace std;

typedef pair<int,int> P;
typedef pair<int,P> PP;

int siz,segMax[300000],segAdd[300000],bit[300010];

void b_add(int i,int x){
	while(i <= siz){
		bit[i] += x;
		i += i & -i;
	}
}

int sum(int i){
	int s = 0;
	while(i){
		s += bit[i];
		i -= i & -i;
	}
	return s;
}

void add(int a,int b,int x,int k = 0,int l = 0,int r = siz){
	if(b <= l || r <= a) return;
	if(a <= l && r <= b){
		segAdd[k] += x;
		return;
	}
	add(a,b,x,k * 2 + 1,l,(l + r) / 2);
	add(a,b,x,k * 2 + 2,(l + r) / 2,r);
	segMax[k] = max(segMax[k * 2 + 1] + segAdd[k * 2 + 1],segMax[k * 2 + 2] + segAdd[k * 2 + 2]);
}

int get(int a,int b,int k = 0,int l = 0,int r = siz){
	if(b <= l || r <= a) return 0;
	if(a <= l && r <= b) return segMax[k] + segAdd[k];
	return max(get(a,b,k * 2 + 1,l,(l + r) / 2),get(a,b,k * 2 + 2,(l + r) / 2,r)) + segAdd[k];
}

signed main(){
	int n,a[100000],ma = -1,mi = INF,tent = 0,ans = 0;
	bool used[100000] = {};
	vector<int> ls,rs,la,ra,as;
	cin >> n;
	for(int i = 0;i < n;i++){
		cin >> a[i];
		as.push_back(a[i]);
	}
	sort(as.begin(),as.end());
	as.erase(unique(as.begin(),as.end()),as.end());
	for(int i = 0;i < n;i++) a[i] = lower_bound(as.begin(),as.end(),a[i]) - as.begin();
	for(int i = 0;i < n;i++){
		if(ma < a[i]){
			ma = a[i];
			ls.push_back(i);
			la.push_back(a[i]);
			used[i] = true;
		}
	}
	for(int i = n - 1;i >= 0;i--){
		if(mi > a[i]){
			mi = a[i];
			rs.push_back(i);
			ra.push_back(a[i]);
			used[i] = true;
		}
	}
	reverse(rs.begin(),rs.end());
	reverse(ra.begin(),ra.end());
	siz = 1;
	while(siz < n) siz *= 2;
	for(int i = 0;i < n;i++){
		tent += i - sum(a[i] + 1);
		b_add(a[i] + 1,1);
	}
	vector<PP> evt1[100001],evt2[100001];
	for(int i = 0;i < n;i++){
		if(!used[i]){
			int l1 = upper_bound(la.begin(),la.end(),a[i]) - la.begin();
			int l2 = upper_bound(ls.begin(),ls.end(),i) - ls.begin() - 1;
			int r1 = upper_bound(rs.begin(),rs.end(),i) - rs.begin();
			int r2 = lower_bound(ra.begin(),ra.end(),a[i]) - ra.begin() - 1;
			if(l1 <= l2 && r1 <= r2){
				evt1[r1].push_back(mp(2,mp(l1,l2)));
				evt2[r2].push_back(mp(-2,mp(l1,l2)));
			}
			if(l1 > 0 && la[l1 - 1] == a[i]){
				evt1[r1].push_back(mp(1,mp(l1 - 1,l1 - 1)));
				evt2[r2].push_back(mp(-1,mp(l1 - 1,l1 - 1)));
			}
			if(r2 < (int)rs.size() - 1 && ra[r2 + 1] == a[i]){
				evt1[r2 + 1].push_back(mp(1,mp(l1,l2)));
				evt2[r2 + 1].push_back(mp(-1,mp(l1,l2)));
			}
		}
	}
	for(int i = 0;i < n;i++){
		for(PP p : evt1[i]) add(p.second.first,p.second.second + 1,p.first);
		ans = max(ans,get(0,siz));
		for(PP p : evt2[i]) add(p.second.first,p.second.second + 1,p.first);
	}
	if(!tent) cout << ((ls.size() == n) ? 1 : 0) << endl;
	else cout << tent - ans - 1 << endl;
	return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 21228
final_rank: 5

code_snippet: #include <bits/stdc++.h>
#define int long long
#define mp make_pair
#define INF 2e+9
using namespace std;

typedef pair<int,int> P;
typedef pair<int,P> PP;

int siz,segMax[300000],segAdd[300000],bit[100010];

void b_add(int i,int x){
	while(i <= siz){
		bit[i] += x;
		i += i & -i;
	}
}

int sum(int i){
	int s = 0;
	while(i){
		s += bit[i];
		i -= i & -i;
	}
	return s;
}

void add(int a,int b,int x,int k = 0,int l = 0,int r = siz){
	if(b <= l || r <= a) return;
	if(a <= l && r <= b){
		segAdd[k] += x;
		return;
	}
	add(a,b,x,k * 2 + 1,l,(l + r) / 2);
	add(a,b,x,k * 2 + 2,(l + r) / 2,r);
	segMax[k] = max(segMax[k * 2 + 1] + segAdd[k * 2 + 1],segMax[k * 2 + 2] + segAdd[k * 2 + 2]);
}

int get(int a,int b,int k = 0,int l = 0,int r = siz){
	if(b <= l || r <= a) return 0;
	if(a <= l && r <= b) return segMax[k] + segAdd[k];
	return max(get(a,b,k * 2 + 1,l,(l + r) / 2),get(a,b,k * 2 + 2,(l + r) / 2,r)) + segAdd[k];
}

signed main(){
	int n,a[100000],ma = -1,mi = INF,tent = 0,ans = 0;
	bool used[100000] = {};
	vector<int> ls,rs,la,ra,as;
	cin >> n;
	for(int i = 0;i < n;i++){
		cin >> a[i];
		as.push_back(a[i]);
	}
	sort(as.begin(),as.end());
	as.erase(unique(as.begin(),as.end()),as.end());
	for(int i = 0;i < n;i++) a[i] = lower_bound(as.begin(),as.end(),a[i]) - as.begin();
	for(int i = 0;i < n;i++){
		if(ma < a[i]){
			ma = a[i];
			ls.push_back(i);
			la.push_back(a[i]);
			used[i] = true;
		}
	}
	for(int i = n - 1;i >= 0;i--){
		if(mi > a[i]){
			mi = a[i];
			rs.push_back(i);
			ra.push_back(a[i]);
			used[i] = true;
		}
	}
	reverse(rs.begin(),rs.end());
	reverse(ra.begin(),ra.end());
	siz = 1;
	while(siz < n) siz *= 2;
	for(int i = 0;i < n;i++){
		tent += i - sum(a[i] + 1);
		b_add(a[i] + 1,1);
	}
	vector<PP> evt1[100001],evt2[100001];
	for(int i = 0;i < n;i++){
		if(!used[i]){
			int l1 = upper_bound(la.begin(),la.end(),a[i]) - la.begin();
			int l2 = upper_bound(ls.begin(),ls.end(),i) - ls.begin() - 1;
			int r1 = upper_bound(rs.begin(),rs.end(),i) - rs.begin();
			int r2 = lower_bound(ra.begin(),ra.end(),a[i]) - ra.begin() - 1;
			if(l1 <= l2 && r1 <= r2){
				evt1[r1].push_back(mp(2,mp(l1,l2)));
				evt2[r2].push_back(mp(-2,mp(l1,l2)));
			}
			if(l1 > 0 && la[l1 - 1] == a[i]){
				evt1[r1].push_back(mp(1,mp(l1 - 1,l1 - 1)));
				evt2[r2].push_back(mp(-1,mp(l1 - 1,l1 - 1)));
			}
			if(r2 < (int)rs.size() - 1 && ra[r2 + 1] == a[i]){
				evt1[r2 + 1].push_back(mp(1,mp(l1,l2)));
				evt2[r2 + 1].push_back(mp(-1,mp(l1,l2)));
			}
		}
	}
	for(int i = 0;i < n;i++){
		for(PP p : evt1[i]) add(p.second.first,p.second.second + 1,p.first);
		ans = max(ans,get(0,siz));
		for(PP p : evt2[i]) add(p.second.first,p.second.second + 1,p.first);
	}
	if(!tent) cout << ((ls.size() == n) ? 1 : 0) << endl;
	else cout << tent - ans - 1 << endl;
	return 0;
}
accuracy: 0.5700934579439252
time_ms: 70
memory_kb: 15572
final_rank: 18

code_snippet: #include <bits/stdc++.h>
#define int long long
#define mp make_pair
#define INF 2e+9
using namespace std;

typedef pair<int,int> P;
typedef pair<int,P> PP;

int siz,segMax[300000],segAdd[300000],bit[100010];

void b_add(int i,int x){
	while(i <= siz){
		bit[i] += x;
		i += i & -i;
	}
}

int sum(int i){
	int s = 0;
	while(i){
		s += bit[i];
		i -= i & -i;
	}
	return s;
}

void add(int a,int b,int x,int k = 0,int l = 0,int r = siz){
	if(b <= l || r <= a) return;
	if(a <= l && r <= b){
		segAdd[k] += x;
		return;
	}
	add(a,b,x,k * 2 + 1,l,(l + r) / 2);
	add(a,b,x,k * 2 + 2,(l + r) / 2,r);
	segMax[k] = max(segMax[k * 2 + 1] + segAdd[k * 2 + 1],segMax[k * 2 + 2] + segAdd[k * 2 + 2]);
}

int get(int a,int b,int k = 0,int l = 0,int r = siz){
	if(b <= l || r <= a) return 0;
	if(a <= l && r <= b) return segMax[k] + segAdd[k];
	return max(get(a,b,k * 2 + 1,l,(l + r) / 2),get(a,b,k * 2 + 2,(l + r) / 2,r)) + segAdd[k];
}

signed main(){
	int n,a[100000],ma = -1,mi = INF,tent = 0,ans = 0;
	bool used[100000] = {};
	vector<int> ls,rs,la,ra,as;
	cin >> n;
	for(int i = 0;i < n;i++){
		cin >> a[i];
		as.push_back(a[i]);
	}
	sort(as.begin(),as.end());
	as.erase(unique(as.begin(),as.end()),as.end());
	for(int i = 0;i < n;i++) a[i] = lower_bound(as.begin(),as.end(),a[i]) - as.begin();
	for(int i = 0;i < n;i++){
		if(ma < a[i]){
			ma = a[i];
			ls.push_back(i);
			la.push_back(a[i]);
			used[i] = true;
		}
	}
	for(int i = n - 1;i >= 0;i--){
		if(mi > a[i]){
			mi = a[i];
			rs.push_back(i);
			ra.push_back(a[i]);
			used[i] = true;
		}
	}
	reverse(rs.begin(),rs.end());
	reverse(ra.begin(),ra.end());
	siz = 1;
	while(siz < n) siz *= 2;
	for(int i = 0;i < n;i++){
		tent += i - sum(a[i] + 1);
		b_add(a[i] + 1,1);
	}
	vector<PP> evt1[100001],evt2[100001];
	for(int i = 0;i < n;i++){
		if(!used[i]){
			int l1 = upper_bound(la.begin(),la.end(),a[i]) - la.begin();
			int l2 = upper_bound(ls.begin(),ls.end(),i) - ls.begin() - 1;
			int r1 = upper_bound(rs.begin(),rs.end(),i) - rs.begin();
			int r2 = upper_bound(ra.begin(),ra.end(),a[i]) - ra.begin() - 1;
			evt1[r1].push_back(mp(2,mp(l1,l2)));
			evt2[r2].push_back(mp(-2,mp(l1,l2)));
			if(l1 > 0 && la[l1 - 1] == a[i]){
				evt1[r1].push_back(mp(1,mp(l1 - 1,l1 - 1)));
				evt2[r2].push_back(mp(-1,mp(l1 - 1,l1 - 1)));
			}
			if(r2 < rs.size() - 1 && ra[r2 + 1] == a[i]){
				evt1[r2 + 1].push_back(mp(1,mp(l1,l2)));
				evt2[r2 + 1].push_back(mp(-1,mp(l1,l2)));
			}
		}
	}
	for(int i = 0;i < n;i++){
		for(PP p : evt1[i]) add(p.second.first,p.second.second + 1,p.first);
		ans = max(ans,get(0,siz));
		for(PP p : evt2[i]) add(p.second.first,p.second.second + 1,p.first);
	}
	if(!tent) cout << ((ls.size() == n) ? 1 : 0) << endl;
	else cout << tent - ans - 1 << endl;
	return 0;
}
accuracy: 0.5700934579439252
time_ms: 70
memory_kb: 15624
final_rank: 19

code_snippet: #include <bits/stdc++.h>
#define int long long
#define mp make_pair
#define INF 2e+9
using namespace std;

typedef pair<int,int> P;
typedef pair<int,P> PP;

int siz,segMax[300000],segAdd[300000],bit[100010];

void b_add(int i,int x){
	while(i <= siz){
		bit[i] += x;
		i += i & -i;
	}
}

int sum(int i){
	int s = 0;
	while(i){
		s += bit[i];
		i -= i & -i;
	}
	return s;
}

void add(int a,int b,int x,int k = 0,int l = 0,int r = siz){
	if(b <= l || r <= a) return;
	if(a <= l && r <= b){
		segAdd[k] += x;
		return;
	}
	add(a,b,x,k * 2 + 1,l,(l + r) / 2);
	add(a,b,x,k * 2 + 2,(l + r) / 2,r);
	segMax[k] = max(segMax[k * 2 + 1] + segAdd[k * 2 + 1],segMax[k * 2 + 2] + segAdd[k * 2 + 2]);
}

int get(int a,int b,int k = 0,int l = 0,int r = siz){
	if(b <= l || r <= a) return 0;
	if(a <= l && r <= b) return segMax[k] + segAdd[k];
	return max(get(a,b,k * 2 + 1,l,(l + r) / 2),get(a,b,k * 2 + 2,(l + r) / 2,r)) + segAdd[k];
}

signed main(){
	int n,a[100000],ma = -1,mi = INF,tent = 0,ans = 0;
	bool used[100000] = {};
	vector<int> ls,rs,la,ra,as;
	cin >> n;
	for(int i = 0;i < n;i++){
		cin >> a[i];
		as.push_back(a[i]);
	}
	sort(as.begin(),as.end());
	as.erase(unique(as.begin(),as.end()),as.end());
	for(int i = 0;i < n;i++) a[i] = lower_bound(as.begin(),as.end(),a[i]) - as.begin();
	for(int i = 0;i < n;i++){
		if(ma < a[i]){
			ma = a[i];
			ls.push_back(i);
			la.push_back(a[i]);
			used[i] = true;
		}
	}
	for(int i = n - 1;i >= 0;i--){
		if(mi > a[i]){
			mi = a[i];
			rs.push_back(i);
			ra.push_back(a[i]);
			used[i] = true;
		}
	}
	reverse(rs.begin(),rs.end());
	reverse(ra.begin(),ra.end());
	siz = 1;
	while(siz < n) siz *= 2;
	for(int i = 0;i < n;i++){
		tent += i - sum(a[i] + 1);
		b_add(a[i] + 1,1);
	}
	vector<PP> evt1[100001],evt2[100001];
	for(int i = 0;i < n;i++){
		if(!used[i]){
			int l1 = upper_bound(la.begin(),la.end(),a[i]) - la.begin();
			int l2 = upper_bound(ls.begin(),ls.end(),i) - ls.begin() - 1;
			int r1 = upper_bound(rs.begin(),rs.end(),i) - rs.begin();
			int r2 = upper_bound(ra.begin(),ra.end(),a[i]) - ra.begin() - 1;
			evt1[r1].push_back(mp(2,mp(l1,l2)));
			evt2[r2].push_back(mp(-2,mp(l1,l2)));
			if(l1 > 0 && la[l1 - 1] == a[i]){
				evt1[r1].push_back(mp(1,mp(l1 - 1,l1)));
				evt2[r2].push_back(mp(-1,mp(l1 - 1,l1)));
			}
			if(r2 < rs.size() - 1 && ra[r2 + 1] == a[i]){
				evt1[r2 + 1].push_back(mp(1,mp(l1,l2)));
				evt2[r2 + 1].push_back(mp(-1,mp(l1,l2)));
			}
		}
	}
	for(int i = 0;i < n;i++){
		for(PP p : evt1[i]) add(p.second.first,p.second.second + 1,p.first);
		ans = max(ans,get(0,siz));
		for(PP p : evt2[i]) add(p.second.first,p.second.second + 1,p.first);
	}
	if(!tent) cout << ((ls.size() == n) ? 1 : 0) << endl;
	else cout << tent - ans - 1 << endl;
	return 0;
}
accuracy: 0.5700934579439252
time_ms: 70
memory_kb: 15784
final_rank: 20

code_snippet: #include <bits/stdc++.h>
#define int long long
#define INF 2e+9
using namespace std;

typedef pair<int,int> P;

int siz,segMax[300000],segAdd[300000],bit[100010];

void b_add(int i,int x){
	while(i <= siz){
		bit[i] += x;
		i += i & -i;
	}
}

int sum(int i){
	int s = 0;
	while(i){
		s += bit[i];
		i -= i & -i;
	}
	return s;
}

void add(int a,int b,int x,int k = 0,int l = 0,int r = siz){
	if(b <= l || r <= a) return;
	if(a <= l && r <= b){
		segAdd[k] += x;
		return;
	}
	add(a,b,x,k * 2 + 1,l,(l + r) / 2);
	add(a,b,x,k * 2 + 2,(l + r) / 2,r);
	segMax[k] = max(segMax[k * 2 + 1] + segAdd[k * 2 + 1],segMax[k * 2 + 2] + segAdd[k * 2 + 2]);
}

int get(int a,int b,int k = 0,int l = 0,int r = siz){
	if(b <= l || r <= a) return 0;
	if(a <= l && r <= b) return segMax[k] + segAdd[k];
	return max(get(a,b,k * 2 + 1,l,(l + r) / 2),get(a,b,k * 2 + 2,(l + r) / 2,r)) + segAdd[k];
}

signed main(){
	int n,a[100000],ma = -1,mi = INF,tent = 0,ans = 0;
	bool used[100000] = {};
	vector<int> ls,rs,la,ra,as;
	cin >> n;
	for(int i = 0;i < n;i++){
		cin >> a[i];
		as.push_back(a[i]);
	}
	sort(as.begin(),as.end());
	as.erase(unique(as.begin(),as.end()),as.end());
	for(int i = 0;i < n;i++) a[i] = lower_bound(as.begin(),as.end(),a[i]) - as.begin();
	for(int i = 0;i < n;i++){
		if(ma < a[i]){
			ma = a[i];
			ls.push_back(i);
			la.push_back(a[i]);
			used[i] = true;
		}
	}
	for(int i = n - 1;i >= 0;i--){
		if(mi > a[i]){
			mi = a[i];
			rs.push_back(i);
			ra.push_back(a[i]);
			used[i] = true;
		}
	}
	reverse(rs.begin(),rs.end());
	reverse(ra.begin(),ra.end());
	siz = 1;
	while(siz < n) siz *= 2;
	for(int i = 0;i < n;i++){
		tent += i - sum(a[i] + 1);
		b_add(a[i] + 1,1);
	}
	vector<P> evt1[100001],evt2[100001];
	for(int i = 0;i < n;i++){
		if(!used[i]){
			int l1 = upper_bound(la.begin(),la.end(),a[i]) - la.begin();
			int l2 = upper_bound(ls.begin(),ls.end(),i) - ls.begin() - 1;
			int r1 = upper_bound(rs.begin(),rs.end(),i) - rs.begin();
			int r2 = upper_bound(ra.begin(),ra.end(),a[i]) - ra.begin() - 1;
			evt1[r1].push_back(P(l1,l2));
			evt2[r2].push_back(P(l1,l2));
		}
	}
	for(int i = 0;i < n;i++){
		for(P p : evt1[i]) add(p.first,p.second + 1,1);
		ans = max(ans,get(0,siz));
		for(P p : evt2[i]) add(p.first,p.second + 1,-1);
	}
	if(!tent) cout << ((ls.size() == n) ? 1 : 0) << endl;
	else cout << tent - ans * 2 - 1 << endl;
	return 0;
}
accuracy: 0.5700934579439252
time_ms: 70
memory_kb: 14588
final_rank: 17