// NOTE: This doesn't handle duplicate elements correctly. #include #include #include #include #include #include #include using namespace std; template struct FenwickTree { // Use 0 based indices. int n; vector tree; FenwickTree(int n_) : n(n_ + 1) { tree.assign(n + 1, 0); } template FenwickTree(int n, F f) : n(n) { tree.assign(n + 1, 0); for(int b = 1; b <= n; b *= 2) for(int i = b; i <= n; i += 2 * b) { tree[i] += f(i - 1); if(i + b <= n) tree[i + b] += tree[i]; } } T query(int r) const { // [0, r] assert(r + 1 <= n); T s = 0; for(++r; r > 0; r -= (r & (-r))) s += tree[r]; return s; } void update(int i, T v) { for(++i; i <= n; i += (i & (-i))) tree[i] += v; } }; int main() { int n; cin >> n; vector h(n), g(n); for(auto& x : h) cin >> x; for(auto& x : g) cin >> x; vector ph(n), pg(n), phi(n), pgi(n); iota(begin(ph), end(ph), 0); iota(begin(pg), end(pg), 0); // ph[i] and pg[i] indicate the position of the i'th smallest element in h and g. // phi[i] and pgi[i] indicate the index of g[i] in ph[i]. stable_sort(begin(ph), end(ph), [&](int i, int j) { return h[i] < h[j]; }); stable_sort(begin(pg), end(pg), [&](int i, int j) { return g[i] < g[j]; }); for(int i = 0; i < n; ++i) phi[ph[i]] = i, pgi[pg[i]] = i; FenwickTree ht(n), gt(n); // For each height h that moves from position i to j, compute the number of taller people to // the left of it. Add the difference to the answer. long long ans = 0; for(int k = 0; k < n; ++k) { // i moves to position j int i = ph[k]; int j = pg[k]; ht.update(i, 1); gt.update(j, 1); ans += abs((i - ht.query(i)) - (j - gt.query(j))); } cout << ans << endl; // Now compute the moves. set large_pos; for(int i = 0; i < n; ++i) large_pos.insert(large_pos.end(), i); auto make_swap = [&](int i, int j) { static int moves = 0; swap(phi[i], phi[j]); swap(ph[phi[i]], ph[phi[j]]); cout << i + 1 << ' ' << j + 1 << '\n'; if(++moves == 200'000) exit(0); }; for(int k = 0; k < n; ++k) { // The k'th smallest value at position i needs to move to position j const int i = ph[k]; const int j = pg[k]; auto it = large_pos.find(i), nit = it; assert(large_pos.contains(j)); if(i < j) { while(*it != j) { // If a swap would swap two equal values, instead we need to find a larger value and // move it through both/all equal values in the current range. make_swap(*it, *next(it)); ++it; } } else { while(*it != j) { // If a swap would swap two equal values, instead we need to find a larger value and // move it through both/all equal values in the current range. make_swap(*it, *prev(it)); --it; } } large_pos.erase(j); } }