#include using namespace std; #define rep(i, a, b) for(int i = a; i < (b); ++i) #define trav(a, x) for(auto& a : x) #define all(x) x.begin(), x.end() #define sz(x) (int)(x).size() typedef long long ll; typedef pair pii; typedef pair pll; typedef vector vi; typedef vector vl; struct FT { vector s; FT(int n) : s(n) {} void update(int pos, ll dif) { // a[pos] += dif for (; pos < sz(s); pos |= pos + 1) s[pos] += dif; } ll query(int pos) { // sum of values in [0, pos) ll res = 0; for (; pos > 0; pos &= pos - 1) res += s[pos-1]; return res; } }; struct Tree { typedef int T; static constexpr T unit = INT_MIN; T f(T a, T b) { return max(a, b); } // (any associative fn) vector s; int n; Tree(int n = 0, T def = unit) : s(2*n, def), n(n) {} void update(int pos, T val) { for (s[pos += n] = val; pos /= 2;) s[pos] = f(s[pos * 2], s[pos * 2 + 1]); } T query(int b, int e) { // query [b, e) T ra = unit, rb = unit; for (b += n, e += n; b < e; b /= 2, e /= 2) { if (b % 2) ra = f(ra, s[b++]); if (e % 2) rb = f(s[--e], rb); } return f(ra, rb); } int bigger_next(int i, int x, bool before){ if(before){ int L = 0; int R = i; while(L < R-1){ int MID = (L+R)/2; if(query(MID, i) > x){ L = MID; } else{ R = MID; } } return L; } else{ int L = i; int R = n-1; while(L < R-1){ int MID = (L+R)/2; if(query(i+1, MID+1) > x){ R = MID; } else{ L = MID; } } return R; } } }; int n; const int MAX_SWAPS = 200000; vi A,B,C,AI,AC; unordered_map M; vi inv1,inv2; vector ANS; vi get_inv(vi &X){ FT ft(n); unordered_map seen; vi res(n); rep(c1,0,n){ if(seen.find(X[c1]) == seen.end()){ seen[X[c1]] = 0; } seen[X[c1]]++; int a = M[ll(X[c1])*ll(n) + seen[X[c1]]]; int invs = c1 - ft.query(a); res[a] = invs; ft.update(a, 1); } return res; } void make_move(int a, bool dec, Tree *segment_tree){ int i = AI[a]; int j = segment_tree->bigger_next(i, a, dec); if(A[i] == A[j])make_move(AC[j], dec, segment_tree); if(sz(ANS) >= MAX_SWAPS)return; if(dec)inv1[a]--; if(!dec)inv1[a]++; ANS.push_back({i, j}); segment_tree->update(i, AC[j]); segment_tree->update(j, AC[i]); swap(AC[j], AC[i]); swap(A[i], A[j]); AI[AC[i]] = i; AI[AC[j]] = j; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); cin >> n; rep(c1,0,n){ int a; cin >> a; A.push_back(a); C.push_back(a); AI.push_back(0); } rep(c1,0,n){ int a; cin >> a; B.push_back(a); } sort(all(C)); unordered_map seen; rep(c1,0,n){ if(seen.find(C[c1]) == seen.end()){ seen[C[c1]] = 0; } seen[C[c1]]++; M[ll(C[c1])*ll(n) + seen[C[c1]]] = c1; } seen.clear(); rep(c1,0,n){ if(seen.find(A[c1]) == seen.end()){ seen[A[c1]] = 0; } seen[A[c1]]++; int a = M[ll(A[c1])*ll(n) + seen[A[c1]]]; AC.push_back(a); AI[a] = c1; } inv1 = get_inv(A); inv2 = get_inv(B); ll inversions = 0; rep(c1,0,n){ inversions += abs(inv1[c1]-inv2[c1]); } Tree segment_tree(n); rep(c1,0,n){ segment_tree.update(c1, AC[c1]); } rep(c1,0,n){ while(inv1[c1] > inv2[c1]){ make_move(c1, 1, &segment_tree); if(sz(ANS) >= MAX_SWAPS)break; } while(inv1[c1] < inv2[c1]){ make_move(c1, 0, &segment_tree); if(sz(ANS) >= MAX_SWAPS)break; } if(sz(ANS) >= MAX_SWAPS)break; } while(sz(ANS) > MAX_SWAPS){ ANS.pop_back(); } cout << inversions << "\n"; trav(p, ANS){ cout << p.first+1 << " " << p.second+1 << "\n"; } return 0; }