#pragma GCC optimize("Ofast") #pragma GCC target("avx2,bmi2,lzcnt,fma") #include using namespace std; pair op(pair a, pair b) { return {max(a.first, b.first), min(a.second, b.second)}; } pair e() { return {INT_MIN, INT_MAX}; } struct Node { pair val; Node *l, *r; Node(): val(e()), l(nullptr), r(nullptr) {} Node(int v): val({v, v}), l(nullptr), r(nullptr) {} Node(pair v): val(v), l(nullptr), r(nullptr) {} Node(Node* l, Node *r): l(l), r(r) { val = op(l?l->val:e(), r?r->val:e()); } Node* setv(int s, int e, int f, pair v) const { if(s == e) return new Node(v); int m = (s+e)/2; if(f <= m) return new Node((l?l:new Node())->setv(s, m, f, v), r); else return new Node(l, (r?r:new Node())->setv(m+1, e, f, v)); } Node* setv(int s, int e, int f, int v) const { return setv(s, e, f, {v, v}); } pair getv(int x, int y, int sv, int ev) const { if(x <= sv && ev <= y) return val; if(ev < x || y < sv) return e(); int mv = (sv+ev)/2; return op(l?l->getv(x, y, sv, mv):e(), r?r->getv(x, y, mv+1, ev):e()); } }; vector> solve(vector A, vector B, vector> E) { int N = A.size(); vector> conn(N); for(auto& [u, v]: E) { if(u > v) swap(u, v); conn[u].push_back(v), conn[v].push_back(u); } sort(E.begin(), E.end()); priority_queue, vector>, greater>> Q; vector deg(N), color(N, -1); for(int i=0; i exist(conn[u].size()+1); for(int v: conn[u]) { Q.emplace(deg[v]--, v); if(color[v] != -1 && color[v] < (int)exist.size()) exist[color[v]] = 1; } for(int i=0; i<(int)exist.size(); ++i) if(!exist[i]) { color[u] = i; break; } assert(color[u] != -1); } int K = 1+*max_element(color.begin(), color.end()); vector> cliques(K); for(int i=0; i::iterator, vector::iterator)> hamiltonian = [&](vector::iterator st, vector::iterator ed) { int N = distance(st, ed); if(N == 1) return; auto mi = st + N / 2; hamiltonian(st, mi); hamiltonian(mi, ed); vector buffer; buffer.reserve(N); auto l = st, r = mi; while(l != mi || r != ed) { if(l == mi) buffer.push_back(*r++); else if(r == ed) buffer.push_back(*l++); else if(cmp(*l, *r)) buffer.push_back(*l++); else buffer.push_back(*r++); } copy(buffer.begin(), buffer.end(), st); return; }; Node* blank = new Node(); vector idxv(N); vector> ans; auto cliques_by_number = cliques; vector> Aseg(K), Bseg(K); for(int i=0; isetv(0, 2*N-1, A[cliques_by_number[i][j]], idxv[cliques_by_number[i][j]]); Aseg[i][j] = as; } Node* bs = blank; for(int j=(int)cliques[i].size()-1; j>=0; --j) { bs = bs->setv(0, 2*N-1, B[cliques_by_number[i][j]], idxv[cliques_by_number[i][j]]); Bseg[i][j] = bs; } } for(int i=0; i ptr(N); for(int i=0; i> io(cliques[j].size(), e()); for(int u: cliques[j]) { int pos = distance(cliques_by_number[i].begin(), lower_bound(cliques_by_number[i].begin(), cliques_by_number[i].end(), u)); Node* Acur = (pos > 0) ? Aseg[i][pos-1] : blank; Node* Bcur = (pos < (int)cliques_by_number[i].size()) ? Bseg[i][pos] : blank; while(ptr[u]<(int)conn[u].size() && color[conn[u][ptr[u]]] == i) { if(conn[u][ptr[u]] < u) Acur = Acur->setv(0, 2*N-1, A[conn[u][ptr[u]]], e()); else Bcur = Bcur->setv(0, 2*N-1, B[conn[u][ptr[u]]], e()); ++ptr[u]; } int from = max(Acur->getv(0, B[u], 0, 2*N-1).first, Bcur->getv(0, A[u], 0, 2*N-1).first); int to = min(Bcur->getv(A[u], 2*N-1, 0, 2*N-1).second, Acur->getv(B[u], 2*N-1, 0, 2*N-1).second); if(0 <= from && from < N && cliques[i][from] != u) ans.emplace_back(cliques[i][from], u); if(0 <= to && to < N && cliques[i][to] != u) ans.emplace_back(u, cliques[i][to]); } } } sort(ans.begin(), ans.end()); ans.erase(unique(ans.begin(), ans.end()), ans.end()); return ans; } int main() { ios::sync_with_stdio(false); cin.tie(0); int N, M; cin >> N >> M; vector A(N), B(N); for(int&x: A) cin >> x, --x; for(int&x: B) cin >> x, --x; vector> E(M); for(auto& [u, v]: E) { cin >> u >> v; --u; --v; } auto ret = solve(A, B, E); cout << ret.size() << '\n'; for(auto [a, b]: ret) cout << a+1 << " " << b+1 << '\n'; }