/* * @Author: Tifa * @LastEditTime: 2020-11-14 15:13:13 * @Description: Cantor expansion, O(nlogn) */ namespace Cantor_expansion { using std::size_t; constsize_t N = 1e6 + 5; constsize_t MOD = ULLONG_MAX;
size_t n, p[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;
size_t frac[N] = {1}; voidinit(size_t n){ tr.clear(); for (size_t i = 1; i <= n; ++i) frac[i] = i * frac[i - 1] % MOD; }
size_tmain(size_t n, constsize_t a[]){ init(n); size_t ret = 1; for (size_t i = n; i; --i) { p[i] = tr.query(a[i]); tr.modify(a[i]); } for (size_t i = 1; i <= n; ++i) ret = (ret + p[i] * frac[n - i] % MOD) % MOD; return ret; } } // namespace Cantor_expansion
/* * @Author: Tifa * @LastEditTime: 2020-11-14 16:15:29 * @Description: inverse Cantor expansion, O(nlogn) */ namespace inverse_Cantor_expansion { using std::size_t; constsize_t N = 64;
size_t n, p[N];
// based on BIT, need discretization before using 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; }