#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; } }; int n; const int MAX_SWAPS = 200000; struct Node { Node *l = 0, *r = 0; int lo, hi, val = -1; Node(vi& v, int lo, int hi) : lo(lo), hi(hi) { if (lo + 1 < hi) { int mid = lo + (hi - lo)/2; l = new Node(v, lo, mid); r = new Node(v, mid, hi); val = max(l->val, r->val); } else val = v[lo]; } int query(int L, int R) { if (R <= lo || hi <= L) return -1; if (L <= lo && hi <= R) return val; return max(l->query(L, R), r->query(L, R)); } void set(int i, int x) { if(i < lo || i >= hi)return; if(lo == hi-1){ val = x; return; } int mid = lo + (hi - lo)/2; if(i < mid){ l->set(i, x); } else{ r->set(i, x); } val = max(l->val, r->val); } int bigger_before(int i, int x){ // biggest j in [0, i) st. A[j] > x if(val <= x || i < lo)return -1; if(lo == hi-1)return lo; if(i >= hi){ if(r->val <= x){ return l->bigger_before(i, x); } return r->bigger_before(i, x); } int ans = r->bigger_before(i, x); if(ans == -1)ans = l->bigger_before(i, x); return ans; } int bigger_after(int i, int x){ // smallest j in (i, n) st. A[j] > x if(val <= x || i >= hi)return n; if(lo == hi-1)return lo; if(i < lo){ if(l->val <= x){ return r->bigger_after(i, x); } return l->bigger_after(i, x); } int ans = l->bigger_after(i, x); if(ans == n)ans = r->bigger_after(i, x); return ans; } }; vi A,B,C,AI,AC; unordered_map M; vi inv1,inv2; 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; } vector ANS; void make_move(int a, bool dec, Node *segment_tree){ int i = AI[a]; int j; if(dec){ j = segment_tree->bigger_before(i, a); } else{ j = segment_tree->bigger_after(i, a); } ANS.push_back({i, j}); segment_tree->set(i, AC[j]); segment_tree->set(j, AC[i]); swap(AC[j], AC[i]); AI[AC[i]] = i; AI[AC[j]] = j; } int main() { 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]); } Node segment_tree(AC, 0, n); rep(c1,0,n){ rep(c2,0,abs(inv1[c1]-inv2[c1])){ if(sz(ANS) >= MAX_SWAPS)break; make_move(c1, (inv1[c1] > inv2[c1]), &segment_tree); } } cout << inversions << "\n"; trav(p, ANS){ cout << p.first+1 << " " << p.second+1 << "\n"; } return 0; }