//line 1 "answer.cpp" // https://judge.yosupo.jp/submission/70214 #if !__INCLUDE_LEVEL__ #include __FILE__ void solve() { int n; cin >> n; vector h(n); for (int &hi : h) { std::cin >> hi; } { vector c(all(h)); sort(all(c)); rep(i, n) h[i] = lower_bound(all(c), h[i]) - c.begin(); } auto inner_solve = [&] (vector h) -> vector { const noshi91::range_lis_query rlq(h); vector hinv(n); rep(i, n) hinv[i] = n-1-h[i]; const noshi91::range_lis_query rlqinv(hinv); vector result(n, -INFL); ll mid = 1; ll ans = rlqinv.query(0, mid+1) + rlq.query(mid, 3); result[2] = 2+2-ans; rep(i, 3, n-1) { ans = rlqinv.query(0, mid+1) +rlq.query(mid, i+1); while (mid < i-1) { ll ansn = rlqinv.query(0, mid+2) +rlq.query(mid+1, i+1); if (ansn >= ans) {mid++; ans = ansn;} else break; } ans = rlqinv.query(0, mid+1) +rlq.query(mid, i+1); result[i] = i+2-ans; } return result; }; auto lv = inner_solve(h); reverse(all(h)); auto rv = inner_solve(h); reverse(all(rv)); debug(lv); debug(rv); ll ans = INFL; rep(i, 2, n-2) { debug(i, lv[i], rv[i]); chmin(ans, lv[i] + rv[i]); } print(ans); return; } int main() { ll t; cin >> t; rep(t) solve(); return 0; } #else /* References [1] Tiskin, A. (2008).Semi-local string comparison: Algorithmic techniques and applications. Mathematics in Computer Science, 1(4), 571-603. [2] Claude, F., Navarro, G., & Ordónez, A. (2015). The wavelet matrix: An efficient wavelet tree for large alphabets. Information Systems, 47, 15-32. */ // #pragma GCC target("popcnt") #include #include #include #include #include #include namespace noshi91 { namespace range_lis_query_impl { namespace wavelet_matrix_impl { using uint = unsigned int; using ll = long long; static constexpr int w = CHAR_BIT * sizeof(uint); int popcount(uint x) { #ifdef __GNUC__ return __builtin_popcount(x); #else static_assert(w == 32, ""); x -= x >> 1 & 0x55555555; x = (x & 0x33333333) + (x >> 2 & 0x33333333); x = x + (x >> 4) & 0x0F0F0F0F; return x * 0x01010101 >> 24 & 0x3F; #endif } class bit_vector { class node_type { public: uint bit; int sum; node_type() : bit(0), sum(0) {} }; std::vector v; public: bit_vector(const uint n) : v(n / w + 1) {} void set(const uint i) { v[i / w].bit |= uint(1) << i; v[i / w].sum += 1; } void build() { for (int i = 1; i < int(v.size()); i++) { v[i].sum += v[i - 1].sum; } } int rank(const uint i) const { return v[i / w].sum - popcount(v[i / w].bit & ~uint(0) << i % w); } int one() const { return v.back().sum; } }; class wavelet_matrix { private: template static bool test(const I x, const int k) { return (x & I(1) << k) != I(0); } std::vector mat; public: template wavelet_matrix(const int bit_length, std::vector a) : mat(bit_length, bit_vector(a.size())) { const int n = a.size(); std::vector a0; a0.reserve(n); for (int p = bit_length - 1; p >= 0; p--) { bit_vector &v = mat[p]; auto itr = a.begin(); for (int i = 0; i < n; i++) { if (test(a[i], p)) { v.set(i); *itr = a[i]; itr++; } else { a0.push_back(a[i]); } } v.build(); std::copy(a0.begin(), a0.end(), itr); a0.clear(); } } int count_less_than(int l, int r, const ll key) const { int ret = r - l; for (int p = mat.size() - 1; p >= 0; p--) { const bit_vector &v = mat[p]; const int rank_l = v.rank(l); const int rank_r = v.rank(r); if (test(key, p)) { l = rank_l; r = rank_r; } else { ret -= rank_r - rank_l; const int o = v.one(); l += o - rank_l; r += o - rank_r; } } return ret - (r - l); } }; } // namespace wavelet_matrix_impl using wavelet_matrix_impl::wavelet_matrix; using vi = std::vector; using iter = typename vi::iterator; static constexpr int none = -1; vi inverse(const vi &p) { const int n = p.size(); vi q(n, none); for (int i = 0; i < n; i++) { if (p[i] != none) { q[p[i]] = i; } } return q; } void unit_monge_dmul(const int n, iter stack, const iter a, const iter b) { if (n == 1) { stack[0] = 0; return; } const iter c_row = stack; stack += n; const iter c_col = stack; stack += n; const auto map = [=](const int len, const auto f, const auto g) { const iter a_h = stack + 0 * len; const iter a_m = stack + 1 * len; const iter b_h = stack + 2 * len; const iter b_m = stack + 3 * len; const auto split = [=](const iter v, iter v_h, iter v_m) { for (int i = 0; i < n; i++) { if (f(v[i])) { *v_h = g(v[i]); ++v_h; *v_m = i; ++v_m; } } }; split(a, a_h, a_m); split(b, b_h, b_m); const iter c = stack + 4 * len; unit_monge_dmul(len, c, a_h, b_h); for (int i = 0; i < len; i++) { const int row = a_m[i]; const int col = b_m[c[i]]; c_row[row] = col; c_col[col] = row; } }; const int mid = n / 2; map(mid, [mid](const int x) { return x < mid; }, [](const int x) { return x; }); map(n - mid, [mid](const int x) { return x >= mid; }, [mid](const int x) { return x - mid; }); class d_itr { public: int delta; int col; d_itr() : delta(0), col(0) {} }; int row = n; const auto right = [&](d_itr &it) { if (b[it.col] < mid) { if (c_col[it.col] >= row) { it.delta += 1; } } else { if (c_col[it.col] < row) { it.delta += 1; } } it.col += 1; }; const auto up = [&](d_itr &it) { if (a[row] < mid) { if (c_row[row] >= it.col) { it.delta -= 1; } } else { if (c_row[row] < it.col) { it.delta -= 1; } } }; d_itr neg, pos; while (row != 0) { while (pos.col != n) { d_itr temp = pos; right(temp); if (temp.delta == 0) { pos = temp; } else { break; } } row -= 1; up(neg); up(pos); while (neg.delta != 0) { right(neg); } if (neg.col > pos.col) { c_row[row] = pos.col; } } } vi subunit_monge_dmul(vi a, vi b) { const int n = a.size(); vi a_inv = inverse(a); vi b_inv = inverse(b); std::swap(b, b_inv); vi a_map, b_map; for (int i = n - 1; i >= 0; i--) { if (a[i] != none) { a_map.push_back(i); a[n - a_map.size()] = a[i]; } } std::reverse(a_map.begin(), a_map.end()); { int cnt = 0; for (int i = 0; i < n; i++) { if (a_inv[i] == none) { a[cnt] = i; cnt += 1; } } } for (int i = 0; i < n; i++) { if (b[i] != none) { b[b_map.size()] = b[i]; b_map.push_back(i); } } { int cnt = b_map.size(); for (int i = 0; i < n; i++) { if (b_inv[i] == none) { b[cnt] = i; cnt += 1; } } } vi c([](int n) { int ret = 0; while (n > 1) { ret += 2 * n; n = (n + 1) / 2; ret += 4 * n; } ret += 1; return ret; }(n)); unit_monge_dmul(n, c.begin(), a.begin(), b.begin()); vi c_pad(n, none); for (int i = 0; i < int(a_map.size()); i++) { const int t = c[n - a_map.size() + i]; if (t < int(b_map.size())) { c_pad[a_map[i]] = b_map[t]; } } return c_pad; } vi seaweed_doubling(const vi &p) { const int n = p.size(); if (n == 1) { return vi({none}); } const int mid = n / 2; vi lo, hi; vi lo_map, hi_map; for (int i = 0; i < n; i++) { const int e = p[i]; if (e < mid) { lo.push_back(e); lo_map.push_back(i); } else { hi.push_back(e - mid); hi_map.push_back(i); } } lo = seaweed_doubling(lo); hi = seaweed_doubling(hi); vi lo_pad(n), hi_pad(n); std::iota(lo_pad.begin(), lo_pad.end(), 0); std::iota(hi_pad.begin(), hi_pad.end(), 0); for (int i = 0; i < mid; i++) { if (lo[i] == none) { lo_pad[lo_map[i]] = none; } else { lo_pad[lo_map[i]] = lo_map[lo[i]]; } } for (int i = 0; mid + i < n; i++) { if (hi[i] == none) { hi_pad[hi_map[i]] = none; } else { hi_pad[hi_map[i]] = hi_map[hi[i]]; } } return subunit_monge_dmul(std::move(lo_pad), std::move(hi_pad)); } bool is_permutation(const vi &p) { const int n = p.size(); std::vector used(n, false); for (const int e : p) { if (e < 0 || n <= e || used[e]) { return false; } used[e] = true; } return true; } wavelet_matrix convert(const vi &p) { assert(is_permutation(p)); int n = p.size(); vi row; if (n != 0) { row = seaweed_doubling(vi(p.begin(), p.end())); } for (int &e : row) { if (e == none) { e = n; } } int bit_length = 0; while (n > 0) { bit_length += 1; n /= 2; } return wavelet_matrix(bit_length, std::move(row)); } class range_lis_query { int n; wavelet_matrix wm; public: range_lis_query() : range_lis_query(std::vector()) {} explicit range_lis_query(const std::vector &p) : n(p.size()), wm(convert(p)) {} int query(const int left, const int right) const { assert(0 <= left && left <= right && right <= n); return (right - left) - wm.count_less_than(left, n, right); } }; } // namespace range_lis_query_impl using range_lis_query_impl::range_lis_query; } // namespace noshi91 //line 2 "/home/seekworser/.cpp_lib/competitive_library/competitive/std/std.hpp" #include #ifndef LOCAL_TEST #pragma GCC target ("avx") #pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") #endif // LOCAL_TEST using namespace std; using std::cout; // shorten typenames using ll = long long; using pii = pair; using pll = pair; using vi = vector; using vvi = vector; using vvvi = vector; using vl = vector; using vvl = vector; using vvvl = vector; using vb = vector; using vvb = vector; using vvvb = vector; using vc = vector; using vvc = vector; using vvvc = vector; using vd = vector; using vvd = vector; using vvvd = vector; using vs = vector; using vvs = vector>; using vvvs = vector>>; template vector> vv(int h, int w, T val = T()) { return vector(h, vector(w, val)); } template vector>> vvv(int h1, int h2, int h3, T val = T()) { return vector(h1, vector(h2, vector(h3, val))); } template vector>>> vvvv(int h1, int h2, int h3, int h4, T val = T()) { return vector(h1, vector(h2, vector(h3, vector(h4, val)))); } template using priority_queue_min = priority_queue, greater>; // define CONSTANTS constexpr double PI = 3.14159265358979323; constexpr int INF = 100100111; constexpr ll INFL = 3300300300300300491LL; float EPS = 1e-8; double EPSL = 1e-10; template bool eq(const T x, const T y) { return x == y; } template<> bool eq(const double x, const double y) { return (abs(x - y) < EPSL * x || abs(x - y) < EPSL); } template<> bool eq(const float x, const float y) { return abs(x - y) < EPS * x; } template bool neq(const T x, const T y) { return !(eq(x, y)); } template bool ge(const T x, const T y) { return (eq(x, y) || (x > y)); } template bool le(const T x, const T y) { return (eq(x, y) || (x < y)); } template bool gt(const T x, const T y) { return !(le(x, y)); } template bool lt(const T x, const T y) { return !(ge(x, y)); } constexpr int MODINT998244353 = 998244353; constexpr int MODINT1000000007 = 1000000007; // fasten io struct Nyan { Nyan() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(18); } } nyan; // define macros #define all(a) (a).begin(), (a).end() #define sz(x) ((ll)(x).size()) #define rep1(n) for(ll dummy_iter = 0LL; dummy_iter < n; ++dummy_iter) // 0,1,...,n-1 #define rep2(i, n) for(ll i = 0LL, i##_counter = 0LL; i##_counter < ll(n); ++(i##_counter), (i) = i##_counter) // i=0,1,...,n-1 #define rep3(i, s, t) for(ll i = ll(s), i##_counter = ll(s); i##_counter < ll(t); ++(i##_counter), (i) = (i##_counter)) // i=s,s+1,...,t-1 #define rep4(i, s, t, step) for(ll i##_counter = step > 0 ? ll(s) : -ll(s), i##_end = step > 0 ? ll(t) : -ll(t), i##_step = abs(step), i = ll(s); i##_counter < i##_end; i##_counter += i##_step, i = step > 0 ? i##_counter : -i##_counter) // i=s,s+step,..., T max(array& a) { return *max_element(all(a)); }; template T min(array& a) { return *min_element(all(a)); }; template T max(vector& a) { return *max_element(all(a)); }; template T min(vector& a) { return *min_element(all(a)); }; template vector vec_slice(const vector& a, int l, int r) { vector rev; rep(i, l, r) rev.push_back(a[i]); return rev; }; template T sum(vector& a, T zero = T(0)) { T rev = zero; rep(i, sz(a)) rev += a[i]; return rev; }; template bool in_range(const T& val, const T& s, const T& t) { return s <= val && val < t; }; template inline vector& operator--(vector& v) { repe(x, v) --x; return v; } template inline vector& operator++(vector& v) { repe(x, v) ++x; return v; } ll powm(ll a, ll n, ll mod=INFL) { ll res = 1; while (n > 0) { if (n & 1) res = (res * a) % mod; if (n > 1) a = (a * a) % mod; n >>= 1; } return res; } ll sqrtll(ll x) { assert(x >= 0); ll rev = sqrt(x); while(rev * rev > x) --rev; while((rev+1) * (rev+1)<=x) ++rev; return rev; } template inline bool chmax(T& M, const T& x) { if (M < x) { M = x; return true; } return false; } template inline bool chmin(T& m, const T& x) { if (m > x) { m = x; return true; } return false; } int digit(ll x, int d=10) { int rev=0; while (x > 0) { rev++; x /= d;}; return rev; } /** * @brief std.hpp * @docs docs/std/std.md */ //line 3 "/home/seekworser/.cpp_lib/competitive_library/competitive/std/io.hpp" // overload operators (prototypes) template inline istream& operator>>(istream& is, pair& p); template inline istream& operator>>(istream& is, vector& v); template inline ostream& operator<<(ostream& os, const pair& p); template inline ostream& operator<<(ostream& os, const vector& v); template ostream &operator<<(ostream &os, const map &mp); template ostream &operator<<(ostream &os, const set &st); template ostream &operator<<(ostream &os, const multiset &st); template ostream &operator<<(ostream &os, const unordered_set &st); template ostream &operator<<(ostream &os, queue q); template ostream &operator<<(ostream &os, deque q); template ostream &operator<<(ostream &os, stack st); template ostream &operator<<(ostream &os, priority_queue pq); // overload operators template inline istream& operator>>(istream& is, pair& p) { is >> p.first >> p.second; return is; } template inline istream& operator>>(istream& is, vector& v) { repe(x, v) is >> x; return is; } template inline ostream& operator<<(ostream& os, const pair& p) { os << p.first << " " << p.second; return os; } template inline ostream& operator<<(ostream& os, const vector& v) { rep(i, sz(v)) { os << v.at(i); if (i != sz(v) - 1) os << " "; } return os; } template ostream &operator<<(ostream &os, const map &mp) { for (auto &[key, val] : mp) { os << key << ":" << val << " "; } return os; } template ostream &operator<<(ostream &os, const set &st) { auto itr = st.begin(); for (int i = 0; i < (int)st.size(); i++) { os << *itr << (i + 1 != (int)st.size() ? " " : ""); itr++; } return os; } template ostream &operator<<(ostream &os, const multiset &st) { auto itr = st.begin(); for (int i = 0; i < (int)st.size(); i++) { os << *itr << (i + 1 != (int)st.size() ? " " : ""); itr++; } return os; } template ostream &operator<<(ostream &os, const unordered_set &st) { ll cnt = 0; for (auto &e : st) { os << e << (++cnt != (int)st.size() ? " " : ""); } return os; } template ostream &operator<<(ostream &os, queue q) { while (q.size()) { os << q.front() << " "; q.pop(); } return os; } template ostream &operator<<(ostream &os, deque q) { while (q.size()) { os << q.front(); q.pop_front(); if (q.size()) os << " "; } return os; } template ostream &operator<<(ostream &os, stack st) { while (st.size()) { os << st.top() << " "; st.pop(); } return os; } template ostream &operator<<(ostream &os, priority_queue pq) { while (pq.size()) { os << pq.top() << " "; pq.pop(); } return os; } template int print_sep_end(string sep, string end, const T& val) { (void)sep; cout << val << end; return 0; }; template int print_sep_end(string sep, string end, const T1 &val, const T2 &...remain) { cout << val << sep; print_sep_end(sep, end, remain...); return 0; }; template int print(const T &...args) { print_sep_end(" ", "\n", args...); return 0; }; template void flush() { cout << flush; }; template int print_and_flush(const T &...args) { print(args...); flush(); return 0; }; #define debug(...) debug_func(0, #__VA_ARGS__, __VA_ARGS__) // debug print template void input(T &a) { cin >> a; }; template void input(T1&a, T2 &...b) { cin >> a; input(b...); }; #ifdef LOCAL_TEST template void debug_func(int i, const T name) { (void)i; (void)name; cerr << endl; } template void debug_func(int i, const T1 &name, const T2 &a, const T3 &...b) { int scope = 0; for ( ; (scope != 0 || name[i] != ',') && name[i] != '\0'; i++ ) { cerr << name[i]; if (name[i] == '(' || name[i] == '{') scope++; if (name[i] == ')' || name[i] == '}') scope--; } cerr << ":" << a << " "; debug_func(i + 1, name, b...); } template void debug_func(int i, const T1 &name, T2 &a, T3 &...b) { int scope = 0; for ( ; (scope != 0 || name[i] != ',') && name[i] != '\0'; i++ ) { cerr << name[i]; if (name[i] == '(' || name[i] == '{') scope++; if (name[i] == ')' || name[i] == '}') scope--; } cerr << ":" << a << " "; debug_func(i + 1, name, b...); } #endif #ifndef LOCAL_TEST template void debug_func(T &...) {} template void debug_func(const T &...) {} #endif /** * @brief io.hpp * @docs docs/std/io.md */ //line 454 "answer.cpp" #endif