// NOTE: This solution uses the builtin order tree insteead of a custom Fenwick tree. #include #include #include #include #include #include using namespace std; #include #include using namespace __gnu_pbds; template using order_tree = tree, rb_tree_tag, tree_order_statistics_node_update>; // find_by_order(int r) (0-based) // order_of_key(TIn v) // use key pair {value, counter} for multiset/multimap int main() { iostream::sync_with_stdio(false); cin.tie(nullptr); 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; order_tree ht, gt; // 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], j = pg[k]; ht.insert(i); gt.insert(j); ans += abs((i - (int)ht.order_of_key(i)) - (j - (int)gt.order_of_key(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(h[i], h[j]); 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], j = pg[k]; auto it = large_pos.find(i); auto step = [&](auto it) { while(*it != j) { // We can't swap equal elements. Instead, move larger elements found further to the // right to the left of the current point. // 1. Find the first swap of elements >= h[i] with a strictly larger element. auto nit = it; while(h[*it] == h[*nit]) ++nit; // 2. Swap this element backwards a number of time to the position of i. while(nit != it) make_swap(*prev(nit), *nit), --nit; // 3. We have successfully swapped i to the next larger place. ++it; } }; if(j > i) step(it); else step(make_reverse_iterator(next(it))); large_pos.erase(j); } }