Let's define the sum of two permutations \(p\) and \(q\) of numbers \(0, 1, ..., (n - 1)\) as permutation \(\texttt{Perm}((\texttt{Ord}(p)+\texttt{Ord}(q))\bmod n!)\), where \(\texttt{Perm}(x)\) is the x-th lexicographically permutation of numbers \(0, 1, ..., (n - 1)\) (counting from zero), and \(\texttt{Ord}(p)\) is the number of permutation \(p\) in the lexicographical order
For example, \(\texttt{Perm}(0) = (0, 1, ..., n - 2, n - 1)\), \(\texttt{Perm}(n! - 1) = (n - 1, n - 2, ..., 1, 0)\)
Misha has two permutations, \(p\) and \(q\). Your task is to find their sum
Permutation \(a = (a_0, a_1, ..., a_{n - 1})\) is called to be lexicographically smaller than permutation \(b = (b_0, b_1, ..., b_{n - 1})\), if for some k following conditions hold:
/* * @Author: Tifa * @Description: From <https://github.com/Tiphereth-A/CP-archives> * !!! ATTENEION: All the context below is licensed under a * GNU Affero General Public License, Version 3. * See <https://www.gnu.org/licenses/agpl-3.0.txt>. */ #include<bits/stdc++.h> usingnamespace std; namespace Cantor_expansion { using std::size_t; constsize_t N = 2e5 + 5; size_t n; template <const std::size_t N = (std::size_t)1e6 + 5, typename T = std::ptrdiff_t> class BIT { private: T tree[N]; std::size_tlowbit(std::ptrdiff_t x){ return x & (-x); }
public: BIT() { memset(tree, 0, sizeof(tree)); } voidclear(){ memset(tree, 0, sizeof(tree)); } voidmodify(std::size_t pos, T val = 1){ for (std::size_t i = pos; i < N; i += lowbit(i)) tree[i] += val; } T query(std::size_t pos){ T ret = 0; for (std::size_t i = pos; i; i = (std::ptrdiff_t)i - lowbit(i)) ret += tree[i]; return ret; } }; BIT<N> tr; voidmain(size_t p[], size_tconst a[], size_t n){ tr.clear(); for (size_t i = n; i; --i) { p[i] = tr.query(a[i]); tr.modify(a[i]); } } } // namespace Cantor_expansion namespace reverse_Cantor_expansion { using std::size_t; constsize_t N = 2e5 + 5; size_t n; template <const std::size_t N = (std::size_t)1e6 + 5> class BT { std::size_t LOG_N; std::size_t tree[N]; std::size_tlowbit(std::ptrdiff_t x){ return x & (-x); } voidmodify(std::size_t pos, std::size_t val = 1){ for (std::size_t i = pos; i < N; i += lowbit(i)) tree[i] += val; } std::size_tsum(std::size_t pos){ std::size_t ret = 0; for (std::size_t i = pos; i; i = (std::ptrdiff_t)i - lowbit(i)) ret += tree[i]; return ret; } std::size_tquery_rk(std::size_t pos){ std::size_t idx = 0; for (std::size_t i = LOG_N; ~i; --i) { idx += 1 << i; if (idx >= N || tree[idx] >= pos) idx -= 1 << i; else pos -= tree[idx]; } return idx + 1; }
public: BT() { memset(tree, 0, sizeof(tree)); LOG_N = ceil(log2(N)); } voidclear(){ memset(tree, 0, sizeof(tree)); } voidinsert(std::size_t pos){ modify(pos); } voidremove(std::size_t pos){ modify(pos, -1); } std::size_tget_rank(std::size_t num){ returnsum(num - 1) + 1; } std::size_tkth_num(std::size_t k){ returnquery_rk(k); } std::size_tpre(std::size_t num){ returnquery_rk(sum(num - 1)); } std::size_tsuc(std::size_t num){ returnquery_rk(sum(num) + 1); } }; BT<N> tr; voidmain(size_tconst p[], size_t a[], size_t n){ for (size_t i = 1; i <= n; ++i) tr.insert(i); for (size_t i = 1; i <= n; ++i) tr.remove(a[i] = tr.kth_num(p[i] + 1)); } } // namespace reverse_Cantor_expansion constsize_t N = 2e5 + 5; size_t a[N], p[N], q[N]; intmain(){ int n; scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%llu", a + i); ++a[i]; } Cantor_expansion::main(p, a, n); for (int i = 1; i <= n; ++i) { scanf("%llu", a + i); ++a[i]; } Cantor_expansion::main(q, a, n); for (size_t i = n; i; --i) p[i] += q[i]; for (size_t i = n; i; --i) { p[i - 1] += p[i] / (n - i + 1); p[i] %= n - i + 1; } reverse_Cantor_expansion::main(p, a, n); for (int i = 1; i <= n; ++i) printf("%d%c", --a[i], " \n"[i == n]); return0; }